Java 상속 키워드 extends와 implements의 구분

1. 인터페이스와 클래스 간의 상속 규칙

자바에서 키워드를 구분하는 기준은 '구현(Implementation)의 의무가 있는가'입니다.

구분 키워드 설명
클래스 → 클래스 extends 부모의 기능을 물려받아 확장함.
인터페이스 → 인터페이스 extends 규격과 규격을 합쳐 더 큰 규격을 만듦.
클래스 → 인터페이스 implements 인터페이스에 정의된 추상 메서드를 직접 구현함.
인터페이스 → 클래스 불가능 인터페이스는 클래스를 상속(extends)할 수 없음

왜 인터페이스가 인터페이스를 상속할 땐 extends인가요?

인터페이스 간의 상속은 부모 인터페이스의 기능을 자식 인터페이스가 그대로 '확장'하는 개념이기 때문입니다. 자식 인터페이스 역시 추상적인 상태이므로, 메서드 몸통(Body)을 구현할 의무가 없습니다. 그래서 extends를 사용합니다.

왜 클래스가 인터페이스를 상속할 땐 implements인가요?

클래스는 인터페이스라는 '설계도'를 바탕으로 실제로 동작하는 객체를 만들어야 합니다. 인터페이스에 선언된 추상 메서드들을 클래스 내부에서 모두 구현(Implement)해야 할 의무가 생기기 때문에 implements라는 명확한 단어를 사용합니다.

2. 모든 경우에 extends를 쓰면 안 되는 이유

자바 설계자들이 이를 구분해 놓은 데에는 몇 가지 중요한 이유가 있습니다.

다중 상속의 허용 여부 :

  • 자바에서 클래스는 단 하나만 상속(extends)할 수 있습니다 (단일 상속).
  • 반면, 인터페이스는 여러 개를 구현(implements)할 수 있습니다 (다중 구현).
  • 만약 모든 키워드가 extends로 통일된다면, 개발자가 코드를 볼 때 이것이 단일 상속만 가능한 클래스인지, 다중 구현이 가능한 인터페이스인지 직관적으로 알기 어렵습니다.

의도의 명확성 : implements 키워드를 보면 개발자는 "아, 이 클래스는 해당 인터페이스의 모든 메서드를 재정의(Override)했겠구나"라고 바로 인지할 수 있습니다. 이는 코드의 가독성과 유지보수성을 크게 높여줍니다.

요약하자면 : 같은 타입끼리(클래스-클래스, 인터페이스-인터페이스)는 확장(extends), 다른 타입끼리(클래스-인터페이스)는 구현(implements)한다고 기억하시면 됩니다!

3. 적용 예시

// 부모 클래스
class Animal {
    void eat() { System.out.println("먹는다"); }
}

// 인터페이스
interface Flyable {
    void fly();
}

// 클래스는 상속과 구현을 동시에 할 수 있음
class Bird extends Animal implements Flyable {
    @Override
    public void fly() {
        System.out.println("하늘을 난다");
    }
}

 

4. 기출 예제

<21년도 기출문제>

정보시스템감리사 21년도 42번 문제

 

정답은? ② 나 입니다. 

NextGenDrive 클래스가 <<interface>> Drive를 향해 점선과 비어 있는 삼각형 화살표로 연결되어 있습니다. 이는 실체화(Realization) 관계, 즉 인터페이스를 구현하는 것을 의미합니다. 자바(Java)에서 인터페이스를 구현할 때는 extends가 아니라 implements 키워드를 사용해야 합니다. (extends는 클래스 간의 상속에 사용됩니다.)

 

<25년도 기출문제>

 

interface Service { public void doWork(); } 
//Service란 interface 정의. 내부에 추상메서드인 doWork()를 정의함.

class Person { ... } //클래스 Person 생성
class Task { ... }   //클래스 Task 생성

class Staff extends Person implements Service { 
//Staff란 클래스를 생성하고 Person을 상속(extends)합니다.
//또, Staff는 Service란 인터페이스를 구현(implements)합니다.
//주의할 점. Staff가 Person을 상속하고, Service를 구현하는 것입니다.
//Person이 Service란 인터페이스를 구현한 것이 아님.

    public void doWork() { Task t = new Task(); ... }
    //Staff 클래스가 Task클래스를 매서드 내부에서 지역변수(t)로 생성하였습니다.
    //이는 객체 간의 지속적인 연결(연관)이 아니라, 
    //일시적인 사용 관계인 의존(Dependency)관계를 나타냅니다.
}

 

실체화(Realization, 구현) : Staff → Service 점선 화살표와 비어있는 삼각형 머리(▷)를 사용합니다.
일반화(Generalization, 상속) : Staff → Person 실선 화살표와 비어있는 삼각형 머리(▷)를 사용합니다.
의존(Dependency) : Staff → Task 점선 화살표와 일반 화살표 머리(>)를 사용합니다.

 

①번: Service 관계가 실선(상속)으로 표시되어 틀렸습니다.
②번: Service 관계가 실선(상속)으로 표시되어 틀렸습니다.

③번: 
Staff → Service: 점선 + 비어있는 삼각형 (구현 - 맞음)
Staff → Person: 실선 + 비어있는 삼각형 (상속 - 맞음)
Staff → Task: 실선 + 일반 화살표 (연관 - 틀림). 메서드 내부 생성이므로 점선인 '의존'이 더 적절합니다.

④번:
Staff → Service: 점선 + 비어있는 삼각형 (구현 - 맞음)
Staff → Person: 실선 + 비어있는 삼각형 (상속 - 맞음)
Staff → Task: 점선 + 일반 화살표 (의존 - 맞음)

 

따라서 정답은 ④