본문 바로가기
  • 오늘도 한걸음. 수고많았어요.^^
  • 조금씩 꾸준히 오래 가자.ㅎ
카테고리 없음

[JAVA] 자바의 다중상속 (인터페이스와 추상클래스)

by 미노드 2023. 6. 8.

알고 시작해야 할 내용

1. 자바에서 클래스의 다중 상속은 불가능하다.
2. 하지만 인터페이스의 다중 상속은 가능하다. 

인터페이스와 추상 클래스를 사용하는 이유

  • 설계시 인터페이스와 추상클래스를  미리 선언해두면 개발시 기능 구현에만 집중할 수 있다.
  • 개발을 할 때, 패키지 명명 규칙이나 메소드 선언 등 기존에 생각해야할 부분들이 있는데, 인터페이스나 추상클래스대로 이용 하다보니, 개발자는 비즈니스 로직에만 집중할 수 있게 된다.
  • 공통의 인터페이스와 추상 클래스를 선언해두면, 선언과 구현을 구분할 수 있다.

그럼 인터페이스만 있으면 되지, 추상 클래스는 왜 필요한가?

  • 인터페이스를 선언하다보니 어떤 메소드는 미리 선언 해놓을 필요가 있다.
  • 그럼 직접 클래스를 만들면 되지 않나 싶지만 해당 클래스까지 만들기엔 애매할 경우에 만든다.
  • 아주 공통적인 기능을 미리 구현해두면 많은 도움이 된다. 미리 구현한다는 의미는 추상 메서드가 아닌 일반 메서드를 생성한다는 의미다. (그냥 공통 로직으로 클래스를 별도 구현해 두는게 더 도움이 되지만,  추상 클래스란 기능도 있다는걸 알아두자)
  • 미리 구현해두면 좋은 기능은 미리 메서드로 생성해두고, 그렇지 않은 메서드는 추상 메서드로 남겨둔다. (인터페이스를 보완한 클래스라 생각해도 무방하다)

인터페이스 특징 (interface)

  • Interface는 모든 메서드가 추상 메서드인 경우를 뜻한다.
  • 즉, ex) public interface A{ ... } 내의 모든 메서드는 선언만 된 상태일 뿐, 어떠한 기능을 할지 '정의' 되지 않은 상태다.
  • 이렇게 정의 되지 않은 메서드를 '추상 메서드'라고 부른다.
  • 인터페이스 내의 모든 메서드는 추상 메서드로 간주되기에 abstract를 (굳이) 적지 않는다 (어차피 모두 추상 메서드이니)
  • 때문에 인터페이스는 추상 클래스보다 한 단계 더 추상화 된 클래스로 간주된다.
  • 추상 클래스와 달리 다중 상속이 가능하다. 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public interface Dinner2 {
    public static final int value = 100;
    public String str = "s"//static final 생략 가능 
    int LEG_COUNT = 3;
    
    // 인터페이스는 몸통이 없고 정의만 있는 메소드를 가질 수 있음. 이게 추상메소드
    public String getFood();
    
    // 인터페이스는 디폴트 메서드를 가질 수 있음. 자바 8버전 이후부터 지원
    default void printFood() {
        System.out.printf("my food is %s\n", getFood());
    }
    // 인터페이스는 스태틱 메서드를 가질 수 있음. 자바 8버전 이후부터 지원
    static int speed() {
        return LEG_COUNT * 30;
    }
}
 
cs

 

추상 클래스의 특징 (Abstract Class)

  • 최소 하나 이상의 추상 메서드를 가지는 클래스를 의미한다.
  • 추상 메서드가 아닌, 미리 구현된 메서드를 가질 수도 있다는 의미다.
  • 즉 인터페이스와 추상 클래스의 가장 구분되는 특징은, 미리 구현된 메서드를 가지고 있느냐의 차이다.
  • 인터페이스와 마찬가지로, 직접 객체를 구현할 수 없다(=new 연산자를 사용할 수 없다는 의미). 아직 정의되지 않은 메서드(=추상 메서드)가 존재하기 때문이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
abstract class Dinner {
    public static final int value = 100;
    public String str = "s"//static final 생략 가능 
    int LEG_COUNT = 3;
    static int ARM_COUNT = 3;
    
    // 추상메소드 가지려면 abstract 붙여야 한다.
    abstract String getFood();
    
    // 추상클래스는 디폴트 메서드를 가질 수 없음
//    default void printFood() {
//        System.out.printf("my food is %s\n", getFood());
//    }
    
    // 추상클래스는 스태틱 메서드를 가질 수 있음. 자바 8버전 이후부터 지원
    static int speed() {
//        return LEG_COUNT * 30; // LEG_COUNT가 static이 아니라서 불러올시 에러
        return ARM_COUNT * 30;
    }
}
cs

 

왜 인터페이스의 다중 상속은 허용되고,  클래스는 안되는 걸까?

만약 자식클래스가 둘 이상의 클래스로부터 다중 상속을 받는다고 가정하자.

ParentA 부모 클래스에 love() 라는 메서드가 이미 정의되어있고, 마찬가지로 ParentB 라는 부모 클래스에도 love() 메서드가 존재한다. love() 메서드가 동일한 시그니처를 가진다면,  자식클래스는 둘 중 어느것을 상속받아야 할까?

(동일 시그니처 : 메서드의 접근 제어자, 리턴 타입, 메서드 명, 매개변수가 모두 동일함을 의미. 메서드 구현부는 같을수도, 다를 수도 있다.)

자식 클래스 입장에서는, love() 메서드를 상속받을 때, 어느 부모의 메서드를 상속받아야할 지 파악할 수 없게 된다. 이미 구현이 완료된 동일 시그니처의 메서드를 상속받는 일은 결국 불가능하다. 

반면 인터페이스는 다중 상속이 가능하지만, 위의 문제를 피해 갈 수 있다. 왜냐하면 메서드가 정의되지 않았기 때문이다.
즉 선언된 형태의 메서드만 가지는 인터페이스는, 동일 시그니처의 메서드를 얼마든 상속받아도 아무런 문제가 발생하지 않는다.

해당 메서드는 아직 구현되지 않아 자식 클래스에서 새롭게 정의해야 하기 때문이다. 

때문에 다중상속은 추상클래스는 불가능 하나, 인터페이스는 가능하다.