우리가 자바에서 자주 사용하는 추상클래스와 인터페이스는 매우 비슷하지만 약간 다른 기능을 제공하고 있습니다.
그렇다면, 각각의 특징과 사용 방법은 어떻게 될까요?
public abstract class Person {
public int age;
public Persion(int age) {
this.age = age;
}
public abstract void ();
public void heartbeat() {
System.out.println("느린 심장 박동~");
}
...
}
public interface RunBehavior {
int speed = 10;
default void run() {
System.out.println("running speed " + speed);
}
void runFast();
}
정리해보면 다음과 같습니다.
추상클래스 | 인터페이스 | |
필드(변수)포함가능여부 | 가능 | 가능 |
다중상속,구현 가능 | 불가(단일상속만 가능) | 가능(다중구현 가능) + 인터페이스간 다중 상속도 가능 |
추상화된 메소드 제공 | 가능 | 가능 |
구현된 메소드 제공 | 가능 | 가능(default 사용) |
이렇게 보면 인터페이스와 추상클래스의 차이점은 거의 없어보입니다. 인터페이스와 추상 클래스 모두 공통으로 구현된 메소드, 필드 혹은 추상화된 메소드를 가질 수 있습니다.
지금까지의 내용을 약간의 차이점과 공통점을 정리해보자면 아래와 같습니다.
1 필드(변수) 포함 가능 여부
![]() |
![]() |
2 다중 상속, 구현 가능 여부
(3+4) 추상화된 메소드 제공 및 구현된 메소드 제공
우선, 다음과 같이 상황을 가정해보겠습니다.
1) 모든 사람은 심장이 뛰고, 숨을 쉬고, 생각을 합니다. 그렇다면, 이는 인터페이스로 구현하는게 맞을까요? 추상화로 구현하는게 맞을까요?
![]() |
![]() |
2) 모든 사람의 직업은 변할 수 있다.
![]() |
![]() |
왼쪽 사진과 같이 추상 클래스를 제공해, 이를 상속받는 클래스에서 구현을 강제하도록해 다형성을 제공할 수 있지만 ,상속을 받는 클래스에서 전부 override해줘야 하고, 유연하게 변경이 불가능합니다. (= 매우 강한 결합도를 갖고 있어 변경 시, 일일이 변경해줘야함. 따라서, 대처가 어려움!)
반대로, 오른쪽 사진으로 인터페이스의 조합을 통해 만들어 직업이 변해도 유연하게 대처할 수 있습니다.
그래서, 보통은 변하는 부분은 인터페이스의 조합을 통해 유연한 기능을 제공하면서, 변하지 않는 뼈대는 추상클래스를 통한 상속을 통해 제공하는 코드들을 많이 볼 수 있습니다.
(대규모 프로젝트에서 추상 클래스 혹은 인터페이스를 사용하면서, 이들의 변경으로 인한 파급효과는 엄청나게 많은 코드의 변경이 필요할 수 있고, 복잡하게 할 수 있다. 이를 고민하고 어떻게 짜면 더 유연하고, 좋은 코드를 짤 수 있을지 훈련하자.)
끄읏~