수색…


소개

Java 8에 도입 된 Default Method 는 개발자가이 인터페이스의 기존 구현을 깨지 않고 인터페이스에 새로운 메소드를 추가 할 수있게 해줍니다. 인터페이스를 구현하는 클래스가 그 메소드의 구현을 제공하지 못할 때, 인터페이스가 디폴트로서 사용되는 구현을 정의 할 수있는 유연성을 제공합니다.

통사론

  • 공용 기본 무효 methodName () {/ * 메서드 본문 * /}

비고

기본 메소드

  • 인터페이스 내에서 사용할 수 있으므로 기존 서브 클래스가이를 구현하지 않고도 동작을 도입 할 수 있습니다.
  • 하위 클래스 또는 하위 인터페이스로 재정의 할 수 있습니다.
  • java.lang.Object 클래스의 메소드를 오버라이드 (override) 할 수 없습니다.
  • 둘 이상의 인터페이스를 구현하는 클래스가 각 인터페이스에서 동일한 메소드 서명을 사용하여 기본 메소드를 상속하는 경우 다중 상속을 해결할 때 기본 메소드가 아닌 것처럼 자체 인터페이스를 재정의하고 제공해야합니다.
  • 기존 구현을 깨지 않고 동작을 도입하기위한 것이지만 새로 도입 된 기본 메소드와 동일한 메소드 서명을 사용하는 정적 메소드가있는 기존 하위 클래스는 여전히 손상됩니다. 그러나 수퍼 클래스에 인스턴스 메소드를 도입 할 경우에도 마찬가지입니다.



정적 메소드

  • 인터페이스 내에서 사용할 수 있으며 주로 기본 메서드의 유틸리티 메서드로 사용됩니다.
  • 하위 클래스 또는 하위 인터페이스 (해당 하위 클래스는 숨김)로 재정의 할 수 없습니다. 그러나 지금도 정적 메소드의 경우와 마찬가지로 각 클래스 또는 인터페이스마다 고유 한 메소드가있을 수 있습니다.
  • java.lang.Object 클래스의 인스턴스 메소드를 오버라이드 (override) 할 수 없습니다 (현재는 서브 클래스에서도 마찬가지입니다).



다음은 하위 클래스와 수퍼 클래스 간의 상호 작용을 요약 한 표입니다.

- SUPER_CLASS-INSTANCE-METHOD SUPER_CLASS-STATIC-METHOD
SUB_CLASS-INSTANCE-METHOD 우선 적용 생성 - 컴파일 타임 오류
SUB_CLASS-STATIC-METHOD 생성 - 컴파일 타임 오류 숨 깁니다



다음은 인터페이스와 구현 클래스 간의 상호 작용을 요약 한 표입니다.

- 인터페이스 - 기본 메소드 인터페이스 - 정적 메소드
IMPL_CLASS-INSTANCE-METHOD 우선 적용 숨 깁니다
IMPL_CLASS-STATIC-METHOD 생성 - 컴파일 타임 오류 숨 깁니다

참고 문헌 :

  • http://www.journaldev.com/2752/java-8-interface-changes-static-method-default-method
  • https://docs.oracle.com/javase/tutorial/java/IandI/override.html

기본 메소드의 기본 사용법

/**
 * Interface with default method
 */
public interface Printable {
    default void printString() {
        System.out.println( "default implementation" );
    }
}

/**
 * Class which falls back to default implementation of {@link #printString()}
 */
public class WithDefault
    implements Printable
{
}

/**
 * Custom implementation of {@link #printString()}
 */
public class OverrideDefault
    implements Printable {
    @Override
    public void printString() {
        System.out.println( "overridden implementation" );
    }
}

다음 진술

    new WithDefault().printString();
    new OverrideDefault().printString();

이 출력을 생성합니다.

default implementation
overridden implementation

기본 메소드 내 다른 인터페이스 메소드 액세스

기본 메소드 내에서 다른 인터페이스 메소드에 액세스 할 수도 있습니다.

public interface Summable {
    int getA();

    int getB();

    default int calculateSum() {
        return getA() + getB();
    }
}

public class Sum implements Summable {
    @Override
    public int getA() {
        return 1;
    }

    @Override
    public int getB() {
        return 2;
    }
}

다음 명령문은 3 을 인쇄합니다.

System.out.println(new Sum().calculateSum());

기본 메소드는 인터페이스 정적 메소드와 함께 사용할 수 있습니다.

public interface Summable {
    static int getA() {
        return 1;
    }

    static int getB() {
        return 2;
    }

    default int calculateSum() {
        return getA() + getB();
    }
}

public class Sum implements Summable {}

다음 문은 3을 인쇄합니다.

System.out.println(new Sum().calculateSum());

오버라이드 된 기본 메소드에 클래스 구현시 액세스

클래스에서 super.foo() 는 슈퍼 클래스에서만 볼 수 있습니다. super 인터페이스에서 기본 구현을 호출하려면 super 라는 인터페이스 이름을 Fooable.super.foo() 로 한정해야합니다.

public interface Fooable {
    default int foo() {return 3;}
}

public class A extends Object implements Fooable {
    @Override
    public int foo() {
        //return super.foo() + 1; //error: no method foo() in java.lang.Object
        return Fooable.super.foo() + 1; //okay, returns 4
    }
}

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

간단한 대답은 기존 구현을 깨지 않고 기존 인터페이스를 발전시킬 수 있다는 것입니다.

예를 들어, 20 년 전에 발행 한 Swim 인터페이스가 있습니다.

public interface Swim {
    void backStroke();
}

우리는 훌륭한 일을했으며, 인터페이스는 매우 유명합니다. 전 세계에서 많은 구현이 이루어졌으며 소스 코드를 제어 할 수 없습니다.

public class FooSwimmer implements Swim {
    public void backStroke() {
         System.out.println("Do backstroke");
    }
}

20 년이 지난 후에는 인터페이스에 새로운 기능을 추가하기로 결정했지만 인터페이스가 고정 된 것처럼 보이므로 기존 구현을 깨뜨릴 수 있습니다.

다행스럽게도 Java 8은 Default 메소드 라는 새로운 기능을 도입했습니다 .

이제 Swim 인터페이스에 새로운 메소드를 추가 할 수 있습니다.

public interface Swim {
    void backStroke();
    default void sideStroke() {
        System.out.println("Default sidestroke implementation. Can be overridden");
    }
}

이제 인터페이스의 모든 기존 구현이 여전히 작동 할 수 있습니다. 그러나 가장 중요한 것은 새로 추가 된 메서드를 자신의 시간에 구현할 수 있다는 것입니다.

이러한 변화의 가장 큰 이유 중 하나는 자바 컬렉션 프레임 워크에있다. 오라클은 Iterable을 구현 한 기존 코드를 모두 깨지 않으면 서 기존 Iterable 인터페이스에 foreach 메소드를 추가 할 수 없었습니다. 디폴트 메소드를 추가함으로써 기존의 Iterable 구현은 디폴트 구현을 상속받습니다.

클래스, 추상 클래스 및 인터페이스 메소드 우선 순위

추상 선언을 포함한 클래스의 구현은 모든 인터페이스 기본값보다 우선합니다.

public interface Swim {
    default void backStroke() {
        System.out.println("Swim.backStroke");
    }
}

public abstract class AbstractSwimmer implements Swim {
    public void backStroke() {
        System.out.println("AbstractSwimmer.backStroke");
    }
}

public class FooSwimmer extends AbstractSwimmer {
}

다음 진술

new FooSwimmer().backStroke();

생산 가능

AbstractSwimmer.backStroke

public interface Swim {
    default void backStroke() {
        System.out.println("Swim.backStroke");
    }
}

public abstract class AbstractSwimmer implements Swim {
}

public class FooSwimmer extends AbstractSwimmer {
    public void backStroke() {
        System.out.println("FooSwimmer.backStroke");
    }
}

다음 진술

new FooSwimmer().backStroke();

생산 가능

FooSwimmer.backStroke

기본 메소드 다중 상속 충돌

다음 예제를 고려하십시오.

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

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

여기 선언이 인터페이스입니다 default 방법 foo 같은 서명은.

새로운 인터페이스에서이 두 인터페이스를 extend 하려고 시도하면 Java에서이 충돌을 명시 적으로 해결해야하므로 두 인터페이스 중 하나를 선택해야합니다.

먼저 abstract 와 동일한 시그니처로 메소드 foo 를 선언 할 수 있습니다.이 메소드는 AB 동작을 오버라이드합니다.

public interface ABExtendsAbstract extends A, B {
    @Override
    void foo();
}

class ABExtendsAbstractimplement 하면 foo 구현을 제공해야합니다.

public class ABExtendsAbstractImpl implements ABExtendsAbstract {
    @Override
    public void foo() { System.out.println("ABImpl.foo"); }
}

둘째 , 완전히 새로운 default 구현을 제공 할 수 있습니다. 또한 클래스를 구현할 때 재정의 된 기본 메소드액세스 하여 AB foo 메소드의 코드를 재사용 할 수 있습니다.

public interface ABExtends extends A, B {
    @Override
    default void foo() { System.out.println("ABExtends.foo"); }
}

class ABExtendsimplement 하면 foo 구현을 제공 할 필요가 not .

public class ABExtendsImpl implements ABExtends {}


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow