[Java] - 인터페이스 Default Methods, Static Methods

janjanee·2021년 4월 30일
0

Java

목록 보기
2/17
post-thumbnail

인프런 더 자바, Java 8 - 백기선 강의를 듣고 정리한 내용

Default Methods (기본 메소드)

자바 8 이상부터 인터페이스에 기본 메소드(Default Methods)를 사용할 수 있다.

인터페이스에 메소드를 선언하는 것이 아닌 구현체를 제공하는 방법이다.

public interface Foo  {

    void printValue();
		
}

public class DefaultFoo implements Foo{

		String value;
	
		@Override
    public void printValue() {
        System.out.println(this.value);
    }

}

Foo 인터페이스가 있고, DefaultFoo 클래스에서 Foo 인터페이스를 구현한 코드이다.

예시로 인터페이스에 새로운 기능을 추가해야하는 상황이 발생했다.

만약 인터페이스에 메소드를 선언한다면?

→ Foo를 구현한 모든 클래스에서 재정의를 해주어야 한다.

Foo를 구현한 클래스가 한 개라면 간단하겠지만 여러개라면 굉장히 번거로운 작업이다.

이럴 때, Default Methods를 사용하여 구현 클래스를 깨뜨리지 않고 새 기능을 추가할 수 있다.

public interface Foo  {

    void printValue();

    /**
     * @implSpec
     * getValue()로 가져온 문자열을 소문자로 바꿔 출력한다.
     */
    default void printValueLowerCase() {
        System.out.println(getValue().toLowerCase());
    }

    String getValue();
		
}

public class DefaultFoo implements Foo{

    String value;
	
    @Override
    public void printValue() {
        System.out.println(this.value);
    }

    @Override
    public String getValue() {
        return this.value;
    }

}

주의할 점은 Default methods로 만든 기능은 모든 인스턴스에 제공이 되는 기능이다.

따라서 Foo라는 인터페이스를 각각 어떻게 구현했는지에 따라 항상 제대로 동작한다는 보장은 없다.

예를 들어, 어떤 구현체에서 getValue() return 값을 null 이라고 했다면,
printValueLowerCase()는 RuntimeException이 발생한다.

따라서 default methods를 사용하려면 최소한의 노력으로 문서화를 잘 해놓자.

위의 예제 @implSpec과 같은 애노테이션을 사용하여 용도를 작성한다.

다음은 Default Methods의 여러 상황에 대한 내용이다.

default methods가 구현체에서 문제가 된다면, 재정의 할 수도 있다.

public class DefaultFoo implements Foo{

    ...

    @Override
    public void printValueLowerCase() {
        System.out.println(this.value.toLowerCase());
    }

}

Object에서 제공하는 equals, hashcode와 같은 메소드는 default methods로 제공할 수 없다.

public interface Foo  {

    void printValue();
		
    // 컴파일 오류
    default String toString() {

    };

}

인터페이스를 상속받는 인터페이스에서 다시 추상 메소드로 변경할 수 있다.

public interface Bar extends Foo {
    void printNameUpperCase();
}

Foo 인터페이스를 상속받는 Bar 인터페이스에서
default methods였던 printNameUpperCase()를 추상메소드로 변경

두 개의 인터페이스가 같은 default methods를 가진다면 구현체에서 override

public interface Foo  {
    default void print() {
        System.out.println("foo");
    }
}

public interface Bar {
    default void print() {
        System.out.println("bar");
    }

}

public class FooBar implements Foo, Bar{
    @Override
    public void print() {
    	System.out.println("foobar");
    }

}

Foo, Bar 두 개의 인터페이스를 구현하기 때문에 어떤 인터페이스의

print()를 사용할 지 명확하지 않아서 컴파일 오류가 발생한다.

따라서, FooBar 클래스에서 print() 메소드를 override 해야 한다.


Static Methods

해당 타입 관련 헬퍼 또는 유틸리티 메소드를 제공할 때 인터페이스에 Static Methods를 제공

public interface Foo  {

    static void printHello() {
        System.out.println("Hello");
    }

}

public class App {

    public static void main(String[] args) {
        Foo.printHello();
    }

}

일반적인 static 메소드 사용법과 동일하다.


References

profile
얍얍 개발 펀치

0개의 댓글