[effective java] (5) Abstract class 보다는 Interface를 우선하라

orca·2022년 11월 11일
0

effective java

목록 보기
5/8

자바의 본질을 실무에 적용하는 이펙티브 자바 강의를 듣고 정리한 내용입니다

Abstract Class vs Interface

Abstract Class란?

추상 클래스는 일반 클래스와는 달리 단독으로 객체를 생성할 수 없다.
반드시 추상 클래스를 상속한 실제 클래스를 통해서만 객체를 생성할 수 있다.

점프투자바

인스턴스화 될 수 없으며, extends를 통해서 자식 클래스에 의해 완성됨
추상 클래스는 여러 클래스에서 공통으로 쓰는 property와 method를 모아두는 용도로 사용함

Interface란?

유지보수에서 인터페이스(interface)는 SOLID를 구현하고, 객체 지향 개발을 하는데 큰 도움을 줍니다.
...
인터페이스는 객체를 어떻게 구성해야 하는지 정리한 설계도입니다.
...
객체가 인터페이스를 사용하면, 인터페이스 메서드를 반드시 구현해야 하는 제약을 합니다.

자바 인터페이스(Java Interface)는 무엇인가?

인터페이스는 특정 기능을 개발할 때 공통적인 기능을 명시하고 강제적으로 구현하게 하는 용도로 사용됨
추상 클래스보다 추상화 단계가 높다

차이점

자바8 버전 이후부터는 디폴트 메서드(default method)를 사용할 수 있다.
인터페이스의 메서드는 몸통(구현체)을 가질 수 없지만 디폴트 메서드를 사용하면 실제 구현된 형태의 메서드를 가질 수 있다.
점프투자바

자바8 버전 이후 디폴트 메서드의 사용으로 인터페이스와 추상 클래스의 차이가 모호해짐

가장 큰 차이는 추상 클래스의 자식 클래스는 하나의 클래스만 extends 할 수 있지만,
인터페이스의 구현 클래스는 여러개의 인터페이스를 implements 할 수 있다

추상 클래스보다는 인터페이스를 사용하는 것이 좋은 디자인

Interface가 더 나음

왜인지 생각해보자

아래와 같이 배달앱 서비스가 있다고 가정하자

public class Restaurant extends Delivery {
    @Override
    public void info() {
        super.info();
    }
}    
public abstract class Delivery {
    public void info(){
        System.out.println("배달주문이 들어왔습니다");
    }
}

원래는 배달 기능만 있었는데 포장 기능이 추가되어야 하는 상황이라면 ?
추상 클래스의 자식 클래스는 하나의 클래스만 extends 할 수 있어서 문제가 생김

인터페이스로 대체

public class Restaurant implements Delibariable, Packable {
  
}
public interface Delibariable {
    default void deliveryOrder(){
        System.out.println("배달주문이 들어왔습니다");
    }
}
public interface Packable {
    default void packOrder(){
        System.out.println("포장 주문이 들어왔습니다");
    }
}

인터페이스에서 default method 사용시,
두 인터페이스의 default method 이름이 같다면 해당 인터페이스를 상속받는 클래스에서 diamond problem 생길 수 있다는 점도 유의하자

default method가 아니면 해당 문제 발생하지 않음

짚고 넘어가는 diamod problem

Why doesn't the diamond problem occur with interfaces in Java?

The diamond problem is what happens when you inherit multiple implementations for the same method and it’s ambiguous as to which you should choose.
Interfaces don’t result in the same ambiguity because they have no implementations.

Diamond problem은 추상적인 메서드에 대해 여러 구현체가 있을 때 발생함

원래 인터페이스는 구현체가 없기 때문에 이러한 모호성이 발생하지 않음
인터페이스에서 실체가 있는 메서드인 default method 사용시 diamond problem 발생하는 이유

추상 클래스를 이용할 때 diamond problem 발생 예시

abstract class Animal { 
	public asbtract void speak(); 
} 
class Dog extends Animal { 
	public void speak() { 
		print("Woof!"); 
	} 
} 
class Cat extends Animal { 
	public void speak() { 
		print("Meow!"); 
	} 
} 
class Catdog extends Cat, Dog {} 
 
a = new Catdog(); 
a.speak(); // the diamond problem: what does it say? 

0개의 댓글