[Java] 인터페이스 Default Method & Static Method

Minjun Kang·2022년 12월 28일
0

basic-java

목록 보기
3/5

인터페이스

자바8 이전 까지는 인터페이스는 단순히 추상 메소드 리스트로 이루어진 일종의 Description이였다.

애초에 Abstract Class가 가지고 있는 다중 상속 문제에 대한 대안으로 인터페이스가 등장하였는데, 인터페이스 그 자체도 가지는 한계점이 많았다.

대표적으로

1. 해당 인터페이스를 구현하는 Concrete 클래스에서 매번 메소드를 재정의 해야만 한다.

  • 인터페이스에 새로운 feature가 추가된다면, 해당 인터페이스를 구현하는 모든 Concrete 클래스를 찾아 해당 Feature를 재정의해야했다.

2. 인터페이스를 구현하는 모든 Concrete 클래스가 가지는 공통적인 메소드를 표현할 수 없었다.

  • 재정의가 필요없는 메소드들도, 모두 Concrete 클래스에서 재정의해야했다.

3. 인터페이스를 구현하는 하위 계층에서 재정의를 막을 수 없었다.

  • 인터페이스 내에서 불변하는 행위를 표현하기 위해서 재정의를 막아야하는 경우가 존재한다.
  • 추상 클래스는 특정 메소드의 재정의를 막는 방법들이 존재한다. 하지만, 자바8 이전까지 인터페이스는 이러한 방법을 제공하지 못했다.

여담으로

위의 한계점들로 인해서, 인터페이스들의 Default method를 간접적으로 표현하는 방식으로 자바8 이전까지는 아래와 같은 방법을 사용했다.

  • 골격 구현(skeleton implementation)
    interface를 구현하는 추상 클래스를 정의, 해당 추상 클래스에 Default 메소드를 정의하여 Concrete 클래스에서는 해당 골격 클래스를 상속받아 필요한 메소드만 재정의하는 방식

    하지만, Concrete 클래스인 A, B, C는 다른 클래스를 extends 하지 못한다는 한계점이 존재한다.

두둥.. 그래서 등장했다!!

Default Method in Interface

  • 인터페이스를 구현하는 Concrete 클래스중 일부만 자신의 특수한 행위를 재정의하고 싶을 때만 재정의할 수 있도록 도와준다. ("기본적으로 ~라는 일을 수행하지만, 필요에 따라 재정의할 수 있어")
// Base Interface
public interface Hi {
	default void sayHello() {
    	System.out.println("안녕!");
    };
}
// Korea는 Hi인터페이스의 sayHello() 기본동작을 수정하지 않아도 된다.
public class Korea implements Hi {
	public String lang = "KOR";
}
// US는 Hi인터페이스의 sayHello()를 재정의해야한다.
public class US implements Hi {
	public String lang = "ENG";
    @Override
    void sayHello() {
    	System.out.println("Hello!");
    }
}

여기서 또 의문이 발생한다.

과연, 동일한 이름의 Default method를 가지는 인터페이스를 여러 개 implement한다면 다중 상속과 관련된 문제가 발생하지 않을까?

이러한 문제점을 사전에 막고자, 동일한 이름의 Default method를 구현하는 Concrete class는 Default method지만, 반드시 재정의 해주도록 컴파일 단계에서 막는 것으로 해결하였다.

public interface Grand {
	default void hello() {
    	System.out.println("Grand!!");
    }
}
public interface Parent {
	default void hello() {
    	System.out.println("Parent!!");
    }
}
// 동일한 이름을 가진 Default method를 여러 개 상속받을 경우, 반드시 재정의
public class Child implements Grand, Parent {
	@Override
    void hello() {
    	System.out.println("Child!!");
    }
}

Static Method in Interface

자바8 이전까지 Interface는 불변하는 행위 에 대한 표현, 그러한 특성을 보존하기 위해 Concrete 클래스에서의 재정의를 막지 못했다.

인스턴스 레벨에서가 아닌 클래스 레벨에서의 특정한 동작을 표현하는 방식이 Class에서는 존재한다. static 메소드이다.

static 메소드는 클래스가 메모리에 로드될 때 정의되므로(컴파일 타임), 런타임에 호출되는 인스턴스 메소드와는 결이 다르다. 그렇기 때문에 런타임 바인딩에 기반을 두는 Overriding자체를 불가능하도록 설계되었다. (@Override 어노테이션이 이를 검사해준다)

자바8 부터 static 키워드를 인터페이스에도 사용할 수 있다!

  • 인터페이스의 static method
public interface A {
	public static sayHello() {
    	System.out.println("hello");
    }
}
// A.sayHello() 와 같이 호출 가능하다!
  • 인터페이스의 static field
    강한 결합을 만드는 안티패턴이지만 설명을 위해 첨부했다.
public interface A {
	public static final int state = 0;
}
profile
성장하는 개발자

0개의 댓글