2022. 3. 29. 22:29ㆍProgramming/Java
[Java] 자바의 추상 클래스 & 인터페이스 정리
Spring을 공부하며 추상 클래스(abstract class), 그리고 인터페이스(interface)의 차이에 대해 확실하게 정리하려고 적게 되었다. 두 개의 개념 모두 상속받는 클래스, 구현하고자 하는 인터페이스 내부의 정의된 메서드를 구현하는 것을 요구한다. 그렇지만 두 개의 개념은 명확히 다형성의 부분에서 차이점이 존재한다.
추상 클래스(abstract class)
추상 클래스는 상속에서 슈퍼 클래스로 사용이 된다.
- abstract로 선언이 된다.
- 슈퍼 클래스로만 사용이 된다.
- 추상 클래스의 경우 내부적으로 미완성의 메서드가 존재할 수 있기에 객체의 생성이 불가능하다.
- 상속을 받은 서브 클래스는 반드시 추상 클래스 내부에서 선언된 모든 추상 메서드들을 구현해야 한다.
- 계층적 상속 관계를 가지는 클래스 구조를 만들 때 적합하다
- 클래스를 상속받아서 이용할 수 있다는 점에서 부모(슈퍼) 클래스의 확장을 한다는 개념이다.
- 인터페이스보단 설계가 되어있는 그런 형태의 클래스이다.
- 모든 클래스는 Object가 상속되어있다.
abstract class Shape{ // 추상 클래스 선언
public Shape(){}
public void paint(){draw();}
abstract public void draw(); // 추상 메서드 선언
}
그럼 이제 추상 클래스를 상속받은 Circle class를 구현해보자
public class Circle extends Shape {
int i = 1;
public int getI() {
return i;
}
@Override
public void draw() {
System.out.println("Circle");
}
}
해당 클래스는 Shape를 상속받았기에 안에 있는 draw를 상속 받아 오버 라이딩을 통해 해당 메서드를 완성해줘야 한다.
그렇기에 해당 메서드 안에 print문을 사용하여 단순한 출력문을 만들었다.
해당 Circle의 객체의 경우 Shape를 상속하여 만들어졌기에 Shape형태로 선언하고 생성자를 Circle로 받아올 수 있다.
이런 경우를 업 캐스팅이라 한다. 다만 위에서 말한바와 같이 모든 클래스는 Object를 상속받고 있기 때문에 Object로 업캐스팅하여 사용이 가능하다.
슈퍼 클래스의 타입 레퍼런스 Shape가 서브 클래스 객체 Circle을 가리키도록 치환되는 것을 의미한다.
다만 이런 업 캐스팅을 통해 접근한 객체의 경우 해당 Circle에 대해서 Circle 클래스 안에 있는 메서드나 필드에 접근할 수 없다.
해당 사진과 같이 s1은 업캐스팅을 통해 접근한 객체이다. 이때 a를 Circle의 getI 메서드를 통해 가져오려 하지만 실제로는 가져오지 못하는 상황을 알 수 있다.
public static void main(String[] args) {
Shape s1 = new Circle();
s1.paint();
}
그렇다면 업 캐스팅한 해당 s1객체에서 paint() 메서드를 실행하게 되면 어떤 결과가 나올까? 먼저 어떤 부분이 출력되는지 확인을 위해 Shape 안의 draw 메서드를 추상 메서드가 아닌 print() 문으로 변경해주었다.
public abstract class Shape{ // 추상 클래스 선언
public Shape(){}
public void paint(){draw();}
public void draw(){
System.out.println("Shape");
};
}
public class Circle extends Shape {
int i = 1;
public int getI() {
return i;
}
@Override
public void draw() {
System.out.println("Circle");
}
public static void main(String[] args) {
Shape s1 = new Circle();
s1.paint();
}
}
결과는 다음과 같다. Shape의 draw 메서드의 출력이 아닌 Circle에서 오버 라이딩, 재작성이 된 메서드가 출력이 되었다.
서브 클래스의 메서드가 호출이 되는 이유는 바로 동적 바인딩(Dynamic binding)이다.
동적 바인딩은 실행할 메서드를 컴파일 시 결정하는 것이(정적 바인딩) 아닌 실행 시 결정하는 것(동적 바인딩)을 말한다.
이때 왜 동적 바인딩인가. 컴파일 단계에서 해당 draw() 메서드가 Shape의 메서드인지 CIrcle의 메서드인지를 판단할 수 없기 때문이다. 그렇지만 실행을 하게 되면 해당 객체가 Shape의 객체인지 Circle의 객체인지를 판단하고 확정을 지어서 해당 Circle의 메서드를 호출하게 되는 것이다.
동적 바인딩을 통해 자바에서는 오버 라이딩이 된 메서드가 있으면 해당 기능을 통해 오버라이딩이 된 메서드가 무조건 실행이 된다고 한다.
사실 이 부분은 추상 클래스의 특징은 아니고 상속받는 클래스, 즉 슈퍼 클래스와 서브 클래스에서의 발생하는 상황이긴하다. 그래도 추상클래스의 주된 목적도 상속을 통해 계층적, 단계적으로 추상화에서 구체화를 시킨다는 목적을 가지고 있다 생각하여 같이 정리를 하게 되었다.
인터페이스(interface)
필드 변수(멤버 변수)는 상속의 대상에 포함되지 않으며 추상 메서드들만 만들 수 있다.
- '규격'
- 클래스끼리의 경우 상속은 단일 상속만 가능하다. 그러나 인터페이스는 다중 구현이 가능하다.
- 인터페이스끼리 상속(extends)이 가능하다. 인터페이스와 클래스 간의 상속은 불가능
- 인터페이스를 구현하여 클래스를 작성하면 인터페이스의 모든 추상 메서드를 구현(implements) 해야 한다.
- 구현하려는 객체가 할 수 있는 동작. 메서드의 명세만 작성이 되어있다.
- 고정이 된 변수(final)를 인터페이스 내의 선언을 하여 사용할 수는 있지만 대체적으로는 메서드의 명세만 넣는다
- 인터페이스 또한 추상 클래스와 마찬가지로 객체의 생성을 하지 못한다.
interface Phone{
final int Button =3; // 가능
int version; // 불가
protected int cnt(); // 불가
void play();
void game();
void call();
}
해당 인터페이스를 IPhone이란 객체로 구현화시켜보았다. 위에서 존재하였던 명세만 되어있던 메서드를 이제 print문을 출력하게 하였다. 이러한 방식처럼 interface의 경우 표현하고자 하는 객체에 대해 명세를 하고 이제 이를 구현하는 클래스는 해당 메서드들에 대해 구현을 하는 것을 목표로 두고 있다.
public class IPhone implements Phone {
@Override
public void play() {
System.out.println("play");
}
@Override
public void game() {
System.out.println("game");
}
@Override
public void call() {
System.out.println("call");
}
}
public static void main(String[] args) {
Phone p = new IPhone();
}
또한 추상 클래스처럼 인터페이스 또한 인터페이스를 구체화한 객체에 맞춰서 업 캐스팅 개념을 도입할 수 있다.
비교
유사한 점
- 객체를 생성할 수 없고, 상속을 위한 슈퍼 클래스로만 사용이 된다
- 클래스의 다형성을 실현하기 위한 목적으로 존재한다
차이점
비교 | 목적 | 구성 |
추상 클래스 | 추상 클래스는 서브클래스에서 존재해햐하는 대부분의 기능을 구현한다. 서브 클래스에서 구현할 수 밖에 없는 기능만을 추상 메서드로 선언하여, 서브 클래스에서 구현하도록 한다 . 상속, 확장하여 사용하기 위한 것 |
추상 메서드와 일반 메서드 모두 포함 상수, 변수 필드 모두 포함 |
인터페이스 | 객체의 기능을 모두 공개한 표준화 문서라 생각하면 좋다 인터페이스를 상속받는 클래스의 목적에 따라 인터페이스의 모든 추상메소드를 만드는것이 목적 동일한 메서드를 보장하기 위해 사용 |
변수 필드는 포함하지 않는다 상수, 추상 / 일반 / default / static 메소드 모두 포함 다중 상속 지원 |
추가
-221129 : 추상 클래스 및 인터페이스 개념에 대한 정리 및 예제 추가 , 동적 바인딩 간단 설명
-22.12.01 : 인터페이스 개념 재정리
'Programming > Java' 카테고리의 다른 글
[Java] 객체지향 (0) | 2022.11.14 |
---|---|
[Java] static 개념 및 정리 (0) | 2022.06.26 |
[ORM - JPA] JPA를 고른 이유 (0) | 2022.03.13 |
[IntelliJ] 단축키 (0) | 2022.03.11 |
[Java] Enum - 열거형 타입(enumerated type) (0) | 2022.03.03 |