1. 소개

Java 인터페이스에 기본 메소드 가 도입된 후 인터페이스와 추상 클래스 사이에 더 이상 차이가 없는 것처럼 보였습니다. 그러나 그렇지 않습니다. 그들 사이에는 몇 가지 근본적인 차이점이 있습니다.

이 예제에서는 인터페이스와 추상 클래스가 어떻게 다른지 자세히 살펴보겠습니다.

2. 기본 방법을 사용하는 이유는 무엇입니까?

기본 방법목적은 기존 구현을 중단하지 않고 외부 기능을 제공 하는 것입니다. 기본 방법을 도입한 원래 동기 는 새로운 람다 함수를 사용하여 Collection Framework에 이전 버전과의 호환성을 제공하는 것이었습니다.

3. 기본 메소드와 추상 클래스 가 있는 인터페이스

주요 근본적인 차이점을 살펴 보겠습니다.

3.1. 상태

추상 클래스 는 상태를 가질 수 있으며 해당 메서드는 구현의 상태에 액세스할 수 있습니다 . 인터페이스에서 기본 메서드가 허용 되지만 구현 상태에 액세스할 수는 없습니다.

기본 메소드에 작성하는 모든 로직 은 인터페이스의 다른 메소드와 관련되어야 합니다. 이러한 메소드는 객체의 상태와 무관합니다 .

CircleClass 객체 의 상태를 나타내기 위해 String , color 를 포함하는 CircleClass 추상 클래스를 생성했다고 가정해 보겠습니다 .

public abstract class CircleClass {

    private String color;
    private List<String> allowedColors = Arrays.asList("RED", "GREEN", "BLUE");

    public boolean isValid() {
        if (allowedColors.contains(getColor())) {
            return true;
        } else {
            return false;
        }
    }

    //standard getters and setters
}

위의 추상 클래스에는 상태에 따라 CircleClass 객체 의 유효성을 검사하는 isValid() 라는 비추상 메서드가 있습니다. isValid() 메서드는 CircleClass 객체의 상태에 액세스 하고 허용 색상을 기반으로 CircleClass 인스턴스의 유효성을 검사 할 수 있습니다. 이 동작으로 인해 객체의 상태를 기반으로 추상 클래스 메서드에 모든 논리를 작성할 수 있습니다 .

CircleClass 의 간단한 구현 클래스를 만들어 보겠습니다 .

public class ChildCircleClass extends CircleClass {
}

이제 인스턴스를 만들고 색상을 확인하겠습니다.

CircleClass redCircle = new ChildCircleClass();
redCircle.setColor("RED");
assertTrue(redCircle.isValid());

여기서 CircleClass 객체에 유효한 색상을 넣고 isValid() 메서드 를 호출하면 내부적으로 isValid() 메서드가 CircleClass 객체 의 상태에 액세스하여 인스턴스에 유효한 색상이 포함되어 있는지 확인할 수 있습니다. .

기본 메서드 가 있는 인터페이스를 사용하여 비슷한 작업을 시도해 보겠습니다 .

public interface CircleInterface {
    List<String> allowedColors = Arrays.asList("RED", "GREEN", "BLUE");

    String getColor();
    
    public default boolean isValid() {
        if (allowedColors.contains(getColor())) {
            return true;
        } else {
            return false;
        }
    }
}

알다시피 인터페이스는 상태를 가질 수 없으므로 기본 메서드는 상태에 액세스할 수 없습니다.

여기에서는 상태 정보를 제공하기 위해 getColor() 메서드를 정의했습니다. 자식 클래스는 런타임에 인스턴스의 상태를 제공하기 위해 getColor() 메서드를 재정의합니다.

public class ChidlCircleInterfaceImpl implements CircleInterface {
    private String color;

    @Override
    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }
}

인스턴스를 만들고 색상을 확인하겠습니다.

ChidlCircleInterfaceImpl redCircleWithoutState = new ChidlCircleInterfaceImpl();
redCircleWithoutState.setColor("RED");
assertTrue(redCircleWithoutState.isValid());

여기에서 볼 수 있듯이 기본 메서드가 런타임에 상태를 확인 하도록 자식 클래스 의 getColor() 메서드를 재정의합니다.

3.2. 생성자

추상 클래스는 생성자를 가질 수 있으므로 생성 시 상태를 초기화할 수 있습니다 . 물론 인터페이스에는 생성자가 없습니다.

3.3. 구문상의 차이점

또한 구문과 관련하여 몇 가지 차이점이 있습니다. 추상 클래스는 Object 클래스 메서드를 재정의할 수 있지만 인터페이스 재정의할 수 없습니다.

추상 클래스 는 가능한 모든 액세스 한정자와 함께 인스턴스 변수를 선언할 수 있으며 자식 클래스에서 액세스할 수 있습니다. 인터페이스는 public, staticfinal 변수만 가질 수 있으며 인스턴스 변수는 가질 수 없습니다.

또한 추상 클래스는 인스턴스와 정적 블록을 선언할 수 있지만 인터페이스는 둘 중 하나를 가질 수 없습니다.

마지막으로 추상 클래스는 람다 식을 참조할 수 없지만 인터페이스는 람다 식을 참조할 수 있는 단일 추상 메서드를 가질 수 있습니다.

4. 결론

이 기사는 추상 클래스와 기본 메소드 가 있는 인터페이스의 차이점을 보여줍니다 . 또한 시나리오에 따라 가장 적합한 것이 무엇인지 확인했습니다.

가능하면 항상 기본 메서드가 있는 인터페이스를 선택해야 합니다. 클래스를 확장 하고 인터페이스도 구현할 수 있기 때문 입니다.

평소와 같이 이 문서에 표시된 모든 코드 샘플은 GitHub에서 사용할 수 있습니다 .

Generic footer banner