인터페이스 디폴트 메서드와 확장
1) 디폴트 메소드 필요성
디폴트 메소드는 인스턴스 메소드이다. 즉, 구현 객체가 있어야 사용할 수 있다.
인터페이스에서 디폴트 메소드를 허용한 이유는 기존 인터페이스를 확장해서 새로운 기능을 추가하기 위해서이다.
위의 그림에서 기존 MyInterface라는 인터페이스에 기능을 추가할 필요가 생겼다.
새롭게 MyInterface에 추상메소드를 선언하면 MyClassA에서 에러가 발생한다.
그 이유는 추가된 추상 메소드에 대한 실체 메소드가 MyClassA에 없기 때문이다.
하지만 인터페이스에 디폴트 메소드를 선언하게 되면 에러가 발생하지 않는다.
디폴트 메소드는 추상메소드가 아니기 때문에 구현 클레스에서 실체 메소드를 작성할 필요가 없기 때문이다.
디폴트 메서소드는 추상 메소드가 구현 클래스에서 실체 메소드로 구현되어야 한다는 제약을 없애준 편의 메소드로 볼 수 있다.
기존 인터페이스
public interface MyInterface {
public void method1();
}
기존 구현 클래스
public class MyClassA implements MyInterface {
@Override
public void method1() {
System.out.println("MyClassA-method1() 실행");
}
}
수정 인터페이스
public interface MyInterface {
public void method1();
//디폴트 메소드
public default void method2() {
System.out.println("MyInterface-method2 실행");
}
}
2) 디폴트 메소드가 있는 인터페이스 상속
부모 인터페이스에 디폴트 메소드가 정의 되어 있을 경우 자식 인터페이스에서 디폴트 메소드를 활용하는 방법
(1) 부모 인터페이스의 디폴트 메소드를 상속받아서 그대로 사용
(2) 부모 인터페이스의 디폴트 메소드를 자식 인터페이스에서 재정의 후 실행 내용을 변경하여 사용
(3) 부모 인터페이스의 디폴트 메소드를 추상 메소드로 재선언하여, 구현 클래스에서 실체 메소드로 구현하여 사용
활용 방법 예시
(1) 부모 인터페이스의 디폴트 메소드를 상속받아서 그대로 사용
부모 인터페이스
public interface ParentInterface {
public void method1();
public default void method2() { /*실행문*/ }
}
자식 인터페이스
public interface ChildInterface1 extends ParentInterface {
public void method3();
}
이 경우 ChildInterface1 인터페이스를 구현하는 클래스는 method1()과 method3()의 실체 메소드를 가지고 있어야하며 ParentInterfaced의 method2()를 호출 할 수 있다.
ChildInterface1 ci1 = new ChildInterface1() {
@Override
public void method1() { /*실행문*/ }
@Override
public void method3() { /*실행문*/ }
};
ci1.method1();
ci1.method2(); //ParentInterface의 method2() 호출
ci1.method3();
(2) 부모 인터페이스의 디폴트 메소드를 자식 인터페이스에서 재정의 후 실행 내용을 변경하여 사용
자식 인터페이스
public interface ChildInterface2 extends ParentInterface {
@Override
public default void method2() { /*실행문*/ }
public void method3();
}
이 경우도 ChildInterface2 인터페이스를 구현하는 클래스는 method1()과 method3()의 실체 메소드를 가지고 있어야하며 ChildInterface2 에서 재정의한 method2()를 호출 할 수 있다.
ChildInterface2 ci2 = new ChildInterface2() {
@Override
public void method1() { /*실행문*/ }
@Override
public void method3() { /*실행문*/ }
};
ci2.method1();
ci2.method2(); //ChildInterface2의 method2() 호출
ci2.method3();
(3) 부모 인터페이스의 디폴트 메소드를 추상 메소드로 재선언하여, 구현 클래스에서 실체 메소드로 구현하여 사용
자식 인터페이스
public interface ChildInterface3 extends ParentInterface {
@Override
public void method2(); //추상메소드로 재선언
public void method3();
}
이 경우도 ChildInterface3 인터페이스를 구현하는 클래스는 method1(), method2(), method3()의 실체 메소드를 모두 가지고 있어야 한다.
ChildInterface3 ci3 = new ChildInterface3() {
@Override
public void method1() { /*실행문*/ }
@Override
public void method2() { /*실행문*/ }
@Override
public void method3() { /*실행문*/ }
};
ci3.method1();
ci3.method2(); //ChildInterface3 구현 객체의 method2() 호출
ci3.method3();
}
참고자료 : 이것이 자바다
'📕 JAVA > 인터페이스' 카테고리의 다른 글
6. 인터페이스 상속 (0) | 2023.03.28 |
---|---|
5. 인터페이스 타입 변환과 다형성 (0) | 2023.03.28 |
4. 인터페이스 사용 (0) | 2023.03.28 |
3. 인터페이스 구현 (0) | 2023.03.28 |
2. 인터페이스 선언 (0) | 2023.03.28 |