👩🏻‍💻 TIL

[Java] 추상 클래스와 인터페이스 차이 (2탄)

ji-hyun 2023. 1. 4. 12:01

Interface 나 abstract Class 는 상속(extends)받거나, 구현(implements) 하는 Class 가 

Interface 나 Abstract Class 안에 있는 Abstract Method 를 구현하도록 강제하는 공통점을 가지고 있다.

 

그렇다면 Interface 와 Abstract Class 두 종류가 존재하는건 왜일까?

결론부터 말하자면, Interface 와 Abstract Class 는 존재 목적이 다르다

 

 

Interface 

Interface 는 부모, 자식 관계인 상속 관계에 얽메이지 않고, 공통 기능이 필요할 때 Abstract Method 를 정의해놓고

구현(implements) 하는 Class 에서 각 기능들을 Overriding 하여 여러가지 형태로 구현할 수 있기에 다형성과 연관되어 있다.

 

예전에 적어놓았던거

2022.06.12 - [TIL] - [Java] 추상 클래스와 인터페이스

 

 

Interface 는 해당 interface 를 구현하는 Class 들에 대해 동일한 method, 동작을 강제하기 위해 존재한다.

(= 몸통을 갖춘 일반 메서드, 멤버 변수를 구성원으로 가질 수 없다)

Java 에서 다중 상속이 안되어 발생하는 Abstract Class 의 한계도 보완해줄 수 있다.

(위에 글 참고하면 다 설명 나와있음)

Interface 의 implements 에는 제한이 없어 다중 구현이 가능하다

 

 

Interface 는 각각 다른 Abstract Class 를 상속하는 Class 들의 공통 기능을 명시할 때 사용하면 편리하다.

(이게 뭔말인지는 예시를 통해 알아볼 것)

 

 

 

 

Abstract Class 

Abstract Class 는 부모와 자식 즉, 상속 관계에서 Abstract Class 를 상속(extends) 받으며 같은 부모 Class(여기서는 

Abstract Class) 를 상속받는 자식 Class 들 간에 공통 기능을 각각 구현하고, 확장시키며 상속과 관련되어 있다.

 

상속은 SuperClass 의 기능을 이용, 확장하기 위해 사용된다

Abstract Class 는 IS - A "~이다" 이고, Interface 는 HAS - A "~을 할 수 있는"이다

 

Abstract Class 를 상속하며 Class 들간의 구분이 가능해진다

 

Java 에서는 다중 상속을 지원하지 않기 때문에 Abstract Class 만으로 구현해야 하는 Abstract Method 를 강제하는데는 한계가

존재한다

 

 

class Vehicle extends Car, Motorcycle {
    @Override
    public void run(){
        super.drive();
    }
}

 

 

만약 Java 에서 다중 상속이 가능했다면 Car, Motocycle 에 각각 drive method 가

정의되어 있을 경우 무엇을 상속받아 Override 한건지 모호해진다

 

이것이 다중 상속의 모호성이고, 이때문에 Java 는 다중 상속을 막아 놓았다

 

 

 

 

 

 

Interface vs Abstract Class 예제

만약 아래와 같은 현실세계의 객체들을 이용해 구현한다고 하면 아래와 같다

 

 

 

 

 

제일 부모 Class인 Creature는 생물에 대한 정의를 내리고 있는 Abstract Class이다.

이를 상속 받는 Animal(동물), Plant(식물) Abstact Class는 각각 동물, 식물의 특성을 abstarct method로 정의해놓는다.
동물(움직이기), 식물(광합성하기) 등..

 

Animal Class를 상속받는 Monkey, Kim, Gil은 각각 원숭이, 사람, 사람으로 사람은 원숭이와 다르게 따로 말을 할 수 있는 기능(Talkable)이 있고, 이 중 Gil이라는 사람 Class는 Program을 할 수 있다.

 

Plant Class를 상속받는 Venus Flytrap은 파리 지옥, 끈끈이 주걱 식물로서, 식물인데도 먹는것이 가능하다.

따라서 Eatable Interface를 사용해 Monkey, Kim, Gil, Venus Flaytrap 모두가 implements한다.

 

여기서 Interface의 사용 목적을 알 수 있는데, Eatable Interface를 사용함으로써 Animal, Plant 각각 다른 부모 Class를 상속받고 있는 Monkey, Kim, Gil, Venus Flaytrap에게 공통적인 기능인 먹는 기능을 Interface를 사용함으로써 상속 관계가 다름에도 기능을 구현하도록 강제 할 수 있다.

 

 

 

 

Abstract Class의 사용 목적을 살펴보면, 사실 위에 Talkable Interface는 동일한 부모 Class인 Animal을 상속받는 Kim, Gil에서 사용하고 있는 기능이다.

이를 새로운 Abstract Class를 생성해서 아래와 같이,

 

 

 

 

 

Animal Class를 상속받는 Human Class에 말하는 기능을 abstarct method로 정의 해놓음으로써, 같은 부모 class를 상속받는 관계에서 공통 기능의 구현을 강제 할 수 있다.

위 그림 예제에서 Eatable Interface와 Human Abstarct Class를 잘 이해한다면, Interface와 Abstract Class의 차이점의 윤곽을 잡을 수 있다.

 

 

 

 

 


추상 클래스

다시 간단히 말하면..

클래스를 설계도라고 한다면, 추상 클래스는 미완성 설계도에 비유할 수 있다

(여기서 클래스가 미완성이라는 것은 추상 메서드를 포함하고 있다는 의미이다.)

 

 

예를 들면, 같은 크기의TV라도 기능의 차이에 따라 여러 종류의 모델이 있지만
설계도 90은 동일할테니, 어느정도 틀을 갖춘 상태에서 진행하는 것이 좋다.
이때 사용할 수 있는 것이 추상 클래스이다.

 

 

추상 메서드 ?

선언부만 작성하고 구현부는 작성하지 않은 채로 남겨 둔 것이 추상메서드이다.
추상 메서드는 상속받는 클래스에 따라 달라질 수 있다.

 

 

 

- 추상 클래스는 키워드 abstract 를 붙여 표현한다

- abstract 로 선언한 메소드를 자식 클래스에서 반드시 구현해야 한다(오버라이딩)

이는 자식 클래스에서 추상 메서드를 반드시 구현하도록 강제하는 것이다

(참고로 추상 메서드는 Interface 에도 존재하나 Interface 와의 차이점은 존재 목적 자체가 아예 다르며, 추상 클래스는 멤버 변수와 몸통이 있는 일반 메서드가 존재한다는 것이다)

 

public abstract class Player {
    boolean pause;
    int currentPos;

    public Player() {
        this.pause = false;
        this.currentPos = 0;
    }
    // 지정된 위치에서 재생을 시작하는 기능 수행되도록 작성
    abstract void play(int pos);
    // 재생을 즉시 멈추는 기능을 수행하도록 작성
    abstract void stop();

    void pause() {
        if (pause) {
            pause = false;
            play(currentPos);
        } else {
            pause = true;
            stop();
        }
    }
}

 

Player 추상 클래스는
VCR이나 Audio 같은 재생이 가능한 기기의 부모 클래스가 될 수 있다.
이제 Player 추상 클래스를 상속받는 CDPlayer 클래스를 만들어보자 🔨

 

 

public class CDPlayer extends Player {
    @Override
    void play(int pos) {
        // 구현 생략
    }

    @Override
    void stop() {
        // 구현 생략
    }

    //CDPlayer 클래스에 추가로 정의된 멤버
    int currentTrack;

    void nextTrack() {
        currentTrack++;
        // ...
    }

    void preTrack() {
        if (currentTrack > 1) {
            currentTrack--;
        }
        // ...
    }
}

 

부모 클래스의 추상 메서드를 CDPlayer 에 맞게 오버라이딩해주고,

CDPlayer 만의 새로운 멤버들을 추가해주었다.

 

 

 

 

 

인터페이스

간단히 말하면...
인터페이스는 일종의 추상 클래스로, 추상 메서드를 갖지만
추상 클래스보다 추상화 정도가 높아
추상 클래스와 달리 몸통을 갖춘 일반 메서드, 멤버 변수를 구성원으로 가질 수 없다.
추상 클래스를 미완성 설계도라 하면, 인터페이스는 구현된 것은 아무 것도 없는,
밑그림만 그려진 기본 설계도라고 할 수 있다.

 

  • 추상 클래스처럼 불완전한 것이기 때문에 그 자체만으로 사용되기 보다,
    다른 클래스를 작성하는데 도움을 줄 목적으로 작성된다.
  • 일반 메서드 또는 멤버 변수를 구성원으로 가질 수 없다.
  • 모든 멤버 변수 public static final 이어햐 하며, 이를 생략할 수 있다.
  • 모든 메서드 public abtract 이어야 하며, 이를 생략할 수 있다.
    (단, JDK1.8부터 static 메서드와 default 메서드를 사용할 수 있다.)

 

 

 

각각의 적절한 사용 케이스 정리

추상 클래스

  • 관련성이 높은 클래스 간에 코드를 공유하고 싶은 경우
  • 추상 클래스를 상속 받을 클래스들이 공통으로 가지는 메소드와 필드가 많거나,
    public이외의 접근자(protected, private) 선언이 필요한 경우
  • non-static, non-final 필드 선언이 필요한 경우 (각 인스턴스에서 상태 변경을 위한 메소드가 필요한 경우)

인터페이스

  • 서로 관련성이 없는 클래스들이 인터페이스를 구현하게 되는 경우.
    ex) Comparable, Cloneable 인터페이스는 여러 클래스들에서 구현되는데, 구현클래스들 간에 관련성이 없다.
  • 특정 데이터 타입의 행동을 명시하고 싶은데, 어디서 그 행동이 구현되는지는 신경쓰지 않는 경우.
  • 다중상속을 허용하고 싶은 경우

 

 

 

 

 

https://velog.io/@new_wisdom/Java-%EC%B6%94%EC%83%81-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4%EC%9D%98-%EC%B0%A8%EC%9D%B4

 

[Java] 추상 클래스와 인터페이스의 차이

[Java] 내가 이해한 추상 클래스와 인터페이스의 차이 정리 👀

velog.io

 

 

 

 

 

 

 

 

'👩🏻‍💻 TIL' 카테고리의 다른 글

[iOS] CocoaPod  (0) 2023.01.12
[iOS] Automatically manage signing  (0) 2023.01.12
Xcode Target, Project  (0) 2022.12.29
[Flutter] 앱 버전관리 규칙  (0) 2022.12.28
안드로이드 인텐트 필터  (0) 2022.12.05