오늘의 주제는 제가 면접에서 나왔던 질문입니다...!
면접자 🧑🏼💻 : 추상클래스와 인터페이스는 차이가 뭔가요?
나 🐥 : (둘이 다르긴..다른데.. 정확히 뭐라고 말해야 하지?)
정말 저 사진처럼 대답을 못하고 나왔습니다... 바보같이...
이런 실무적인 질문이 들어오면 시원하게 대답하기가 생각보다 힘듭니다.
우리는 추상클래스와 인터페이스에 대해서 알고 있냐고 누가 물어본다면 알고 있다고 대답을 하고있습니다.
그런데 이론적인 내용 말고 정작 "왜 사용하나요?", "차이점이 뭔가요?", "추상클래스를 사용할지 인터페이스를 사용할지 어떻게 정하나요?"
오늘 이 글은 읽고 다시한번 기본을 잡는다는 마인드로 한번 글을 써보겠습니다.
추상클래스란?
추상클래스는 일반 클래스와 별 다를 것이 없습니다. 단지, 추상 메서드를 선언하여 상속을 통해서 자손 클래스에서 완성하도록 유도하는 클래스입니다. 그래서 미완성 설계도라고도 표현합니다. 상속을 위한 클래스이기 때문에 따로 객체를 생성할 수 없습니다.
class 앞에 "abstract" 예약어를 사용하여 상속을 통해서 구현해야한다는 것을 알려주고 선언부만 작성하는 추상메서드를 선언할 수 있습니다.
인터페이스란?
추상클래스가 미완성 설계도라면 인터페이스는 기본 설계도라고 할 수 있습니다. 인터페이스도 추상클래스처럼 다른 클래스를 작성하는데 도움을 주는 목적으로 작성하고 클래스와 다르게 다중상속(구현)이 가능합니다.
아니 근데 이 두개 굳이 나누는 이유가 뭐야 복잡하게 하나면 쓰면 안되는건가?🤷🏻♀️
저도 처음 자바를 공부할때 많이 어렵고 헷갈렸습니다. 이 둘의 차이는 뭘까 ?
그 둘의 차이는 추상클래스와 인터페이스의 기능들을 살펴보면 추상클래스가 인터페이스의 역할을 다 할 수 있는데 왜 굳이 인터페이스라는게 있는 걸까요?
이론적인 차이점을 다 제외하고 두개로 나눠서 사용하는 가장 큰 차이점은 사용용도라고 생각합니다.
사용의도 차이점
추상클래스 : IS - A "~이다".
인터페이스 : HAS - A "~을 할 수 있는".
이렇게 구분하는 이유는 다중상속의 가능 여부에 따라 용도를 정한 것 같다고 합니다. 자바의 특성상 한개의 클래스만 상속이 가능하여 해당 클래스의 구분을 추상클래스 상속을 통해 해결하고, 할 수 있는 기능들을 인터페이스로 구현합니다.
뭔가 이렇게 글을 좌르륵 쓰는것보다는 예시를 드는것이 가장 좋겠다고 생각이 들었습니다.
위에 말 처럼 인간과 동물은 생명체를 상속하고 각 생명체들은 구분에 따라 식물과 동물을 상속합니다. 그리고 각각 할 수 있는 기능들을 인터페이스로 구현했습니다.
예시
Creature 추상클래스
abstract class Creature {
// 생물체의 공통 메서드
void breathe() {
System.out.println("Breathing..."); //숨
}
}
기본적으로 생명체는 숨이 있어야 살아 갈 수 있어 추상클래스를 만들었습니다.
abstract void move();
그리고 추상 메서드로는 움직임을 구현했습니다.
각 생물은 구분에 따라 Animal 또는 Plant를 상속합니다.
// Animal 추상 클래스 (동물)
abstract class Animal extends Creature {
// Animal이 가지는 공통 동작을 추상 메서드로 정의
abstract void sound();
}
// Plant 추상 클래스 (식물)
abstract class Plant extends Creature {
// Plant가 가지는 공통 동작을 추상 메서드로 정의
abstract void photosynthesize();
}
Animal을 상속받는 Amazzi(나), Dog, Cat은 Plant와 다르게 bark(짖다) 할 수 있으니 Barkable 인터페이스를 구현하였습니다.
// 짖는 기능을 정의한 Barkable 인터페이스
interface Barkable {
void bark();
}
// 먹을 수 있는 기능을 정의한 Eatable 인터페이스
interface Eatable {
void eat();
}
// 프로그래머의 특성을 정의한 Programmer 인터페이스
interface Programmer {
void code();
}
여기서 눈여겨 볼 것은 바로 Eatable인데, Eatable 인터페이스는 현재 상속 관계가 다른 Amazzi(나),Dog, Cat, FlyHellPlant(파리지옥)에게 공통적인 기능인 Eat 기능을 인터페이스를 사용함으로 같은 기능을 구현하도록 강제하고 있습니다.
그러면 결국 이 4가지 클래스 모두 생물 클래스를 상속하고 있는데, 생물 클래스에 eat이라는 추상 메서드를 만들면 안되는가?라고 생각할 수 있지만 Plant를 상속받은 Rose는 eat 메소드를 가질 수 없습니다.
그러면 어떻게 해야할까요? 🧐
이때 바로 인터페이스로 따로 선언을 해주어 각각 eat을 할 수 있는 클래스에 implements 해주어 만들어주면 가독성이 올라가며 유지보수 또한 쉬워집니다.
정리하자면!
추상 클래스
상속 관계를 쭉 타고 올라갔을때 같은 조상클래스를 상속하는데 기능까지 완변히 똑같은 기능이 필요한 경우
인터페이스
상속 관계를 쭉 타고 올라갔을때 다른 조상클래스를 상속하는데 같은 기능이 필요할 경우 인터페이스 사용
추가
추가적으로 성재님이 인터페이스와 추상클래스 안에 메서드 이름이 같은 경우 사용이 가능한지 질문을 주셨는데..
실제로 구현은 가능하다고 답변을 주셨다!! 정말 도움을 많이 받는거 같다!
reference
https://f-lab.kr/insight/interfaces-and-abstract-classes-in-java
https://myjamong.tistory.com/150
'Java' 카테고리의 다른 글
자바의 Record? 그게 뭐야? (0) | 2025.01.08 |
---|---|
Java 변수의 초기값 (1) | 2024.11.18 |
String / StringBuffer / StringBuilder 차이 (1) | 2024.11.13 |
[JAVA] 실무에서 가장 많이 쓰이는 자바 문법 (0) | 2024.06.12 |
[JAVA] Java String reverse(문자열 뒤집기) (0) | 2024.06.05 |