본문 바로가기

Dot Programming/Java

[Java] 추상 클래스 vs 인터페이스 (추상 클래스와 인터페이스의 차이는 결합력)

    추상 클래스

    클래스 안에 abstract 메서드가 하나라도 있으면 abstract 클래스로 표기해야 한다. 즉, 추상 메서드를 가진 클래스이다. 그 외에는 일반클래스와 전혀 다르지 않다.

    • 생성자, 변수, 메서드 모두 사용 가능 (단, 추상 메서드 1개 이상 필수)
    • 추상 메서드는 private일 수 없다. (접근제어자 생략하면 default)
    • class A implements 추상클래스 (상속의 개념 is-a)
    • 다중상속이 불가능하다.
    abstract class 추상클래스 {
        int val;  // 일반 변수
        추상클래스(){} // 생성자
        public void 일반메서드(){}
        // ...
        // 추상 메서드
        public abstract void 추상메서드(); 
        (default 생략가능) abstract void 추상메서드2(); 
    }
    
    // A는 추상클래스를 상속했다.
    class A extends 추상클래스{
        public void 추상메서드(){
            // 추상메서드 구현 필수
        }
        
        void 추상메서드2(){
            // 추상메서드 구현 필수
        }
    }

     

    인터페이스

    인터페이스는 추상 클래스보다 좀 더 유연한 설계도이다. 즉, 더 추상적이라고 보면 된다. 그래서 오직 추상메서드와 상수만 가질 수 있다. java 8부터는 확장성을 위해 디폴트와 static 메서드 사용이 가능해졌다.

    • 상수(final), 추상 메서드, 디폴트/static 메서드 사용 가능. 생성자를 가질 수 없다 (인스턴스화 불가)
    • 추상 메서드는 public만 가능하다.
    • class A implements 인터페이스 (구현 개념 has-a)
    • 인터페이스끼리 다중상속이 가능하다.
    interface 인터페이스 {
        (public static final 생략가능) int 상수이름 = 값;
        (public abstract 생략가능) void 추상메서드();
    
        default void 디폴트메서드(){
             // 구현
        }
    }
    
    // A는 인터페이스를 구현헀다. 
    class A implements 인터페이스 {
       void 추상메서드(){
            // 추상메서드 구현 필수
       }
    }

     

    추상 클래스 vs 인터페이스

      추상 클래스 인터페이스
    변수 일반 클래스와 동일 (public staic final) 상수 
    메서드 일반 클래스와 동일.
    단, abstract 메서드 무조건 1개 이상
    추상 메서드, 디폴트/static 메서드(jdk 1.8부터)
    메서드 접근제어자 public, protected, deafult(생략가능) public만 (생략가능)
    생성자 o x
    A {extends / implements} B extends / 상속 (is-a) implements / 구현 (has-a)
    A는 B이다 A는 B를 가지고 있다.
    다중상속 불가능 가능

     

    추상 클래스는 단일 상속만 가능하고, 인터페이스는 다중상속(구현)이 가능함을 볼 수 있다. 결합력은 추상클래스 > 인터페이스이다.

     

    추상 클래스와 인터페이스 관계도 예시

     

    인용: 자바의 정석

    추상 클래스

    클래스를 설계도에 비유한다면, 추상클래스는 미완성 설계도에 비유할 수 있다. (완성되지 못한 채 남겨진 설계도) 새로운 클래스가 추상 클래스를 상속받아 추상메서드를 구현해주면 완전한 클래스가 되는 것이다.

    • 같은 TV라도 여러 종류의 모델이 있지만, 사실 이들의 설계는 아마 90%정도 동일할 것이다. 그러면 미완성 설계도를 만들어 놓고, 이 미완성 설계도를 이용해서 완성하는 것이 훨씬 효율적이다.

     

    인터페이스

    인터페이스는 더 추상화된 설계도로, 구현된 것은 아무것도 없고 밑그림만 그려져 있는 기본 설계도이다. 추상클래스처럼 다른 클래스를 작성하는데 도움을 주는 목적으로 작성하고 다중상속(구현)이 가능하다.

     

    인용: 모던 자바 인 액션 ch18 디폴트 메서드

    추상 클래스와 인터페이스는 뭐가 다를까?

    자바 8 이후 부터는 인터페이스도 디폴트 메서드가 도입되어 이젠 둘 다 추상 메서드와 바디를 포함하는 메서드를 정의할 수 있다. 

     

    추상 클래스 vs 인터페이스

    1. 인터페이스 다중 구현: 클래스는 하나의 추상 클래스만 상속받을 수 있지만 인터페이스를 여러 개 구현할 수 있다. 
    2. 추상 클래스 인스턴스 변수 공유: 추상 클래스는 인스턴스 변수(필드)로 공통 상태를 가질 수 있다. 하지만 인터페이스는 인스턴스 변수를 가질 수 없다. 

     

    인용: effective java item 20

    인터페이스와 추상 클래스는 자바가 제공하는 다중 구현 메커니즘이다. 자바 8부터 인터페이스도 디폴트 메서드(default method)를 제공할 수 있게 되어, 이제는 두 메커니즘 모두 인스턴스 메서드를 구현 형태로 제공할 수 있다. 그러면 추상 클래스와 인터페이스와의 차이가 더이상 없는 것일까?

     

    인터페이스와 추상 클래스의 가장 큰 차이는 결합의 정도이다. 

    • 추상 클래스가 정의한 타입을 구현하는 클래스는 반드시 추상 클래스의 하위 클래스가 되어야 한다는 점이다. 자바는 단일 상속만 지원하니, 추상 클래스 방식은 새로운 타입을 정의하는 데 커다란 제약을 갖는다.
    • 인터페이스가 선언한 메서드를 모두 정의하고 그 일반 규약을 잘 지킨 클래스라면 다른 어떤 클래스를 상속했든 같은 타입으로 취급된다.

     

    추상 클래스보다 인터페이스를 우선해야 하는 이유

    1. 기존 클래스에도 손쉽게 새로운 인터페이스를 구현해 넣을 수 있다. (다중 구현)
    2. 믹스인(mixin) 정의에 안성맞춤이다. (추상 클래스로는 믹스인을 정의할 수 없다)
      1. 믹스인이란 클래스가 구현할 수 있는 타입으로, 믹스인을 구현한 클래스에 원래의 ‘주된 타입’ 외에도 특정 선택적 행위를 제공한다고 선언하는 효과를 준다. 예로 Comparable 인터페이스가 있다.
      2. 이처럼 주된 기능에 선택적 기능을 ‘혼합(mixed in)’한다고 해서 믹스인이라 부른다.
    3. 계층구조가 없는 타입 프레임워크를 만들 수 있다.
    4. 래퍼 클래스 관용구(아이템 18)와 함께 사용하면 기능을 향상시키는 안전하고 강력한 수단이 된다.