본문 바로가기

Programming/JAVA

인터페이스(13) - 디폴트 메서드가 있는 인터페이스의 상속

java logo image

 

 

우리는 인터페이스 사이에도 상속관계가 있음을 배웠죠? 그럼 인터페이스의 상속이 이루어진 상태에서, 디폴트 메서드는 어떻게 동작하게 될지에 대해서도 살펴보도록 하겠습니다. 기본적으로는 추상 메서드와 마찬가지로, 디폴트 메서드 역시 상속이 이루어질 것입니다. 

 

하지만, 이런 단순 상속을 통한 디폴트 메서드의 사용 이외에도 몇 가지 사용 방식이 존재합니다. 이 부분에 대해서 다음과 같이 살펴보도록 하겠습니다. 

 

1. 디폴트 메서드를 그냥 상속해서 사용합니다.
2. 디폴트 메서드를 상속한 다음, 오버라이드 합니다. 
3. 디폴트 메서드를 추상 메서드로 재선언 합니다.

 


 

우선, 예제에서 사용할 인터페이스 ParentInterface가 다음과 같습니다. 

 

public interface ParentInterface {
	public void method1();
	public default void method2() {
		System.out.println("디폴트 메서드 method2");
	}
}

 

 

1. 디폴트 메서드 상속해서 사용하기

 

이 경우는 단순합니다. 자식 인터페이스가 본인이 상속한 부모 인터페이스에서 정의한 디폴트 메서드를 원래 있었던 것처럼 사용하는 경우입니다. 위의 부모 인터페이스인 ParentInterface를 상속하는 자식 클래스 ChildInterface가 아래와 같습니다. 

 

public interface ChildInterface1 extends ParentInterface {
	public void method3();
}

 

여기서는 익명 객체 방식을 활용하여, 인터페이스1을 구현해 각각의 메서드를 실행해 보았습니다. 

 

public class ExampleMain {	
	public static void main(String[] args) {
		ChildInterface1 ci1 = new ChildInterface1() {
			@Override
			public void method1() {
				System.out.println("ChildInterface1 - method1 실행");
			}
			
			@Override
			public void method3() {
				System.out.println("ChildInterface1 - method3 실행");
			}
		};
		
		ci1.method1();
		ci1.method2();
		ci1.method3();
	}
}

/* 출력
ChildInterface1 - method1 실행
디폴트 메서드 method2
ChildInterface1 - method3 실행
*/

 

 


 

 

이번에는 자식 인터페이스인 ChildInterface2를 선언해 보겠습니다. 이 자식 인터페이스는, 디폴트 메서드를 오버라이드하고, 자신의 추상 메서드 method3( )을 갖고 있게 됩니다. 

 

이를 역시 익명 인터페이스 객체 타입으로 선언하고 각 메서드를 함께 실행해 보겠습니다. 

 

package chap06.class00;

public class ExampleMain {	
	public static void main(String[] args) {
		ChildInterface1 ci1 = new ChildInterface1() {
			@Override
			public void method1() {
				System.out.println("ChildInterface1 - method1 실행");
			}
			
			@Override
			public void method3() {
				System.out.println("ChildInterface1 - method3 실행");
			}
		};
		
		ci1.method1();
		ci1.method2();
		ci1.method3();
		
		
		ChildInterface2 ci2 = new ChildInterface2() {
			@Override
			public void method1() {
				System.out.println("ChildInterface2 - method1 실행");
			}
			
			@Override
			public void method3() {
				System.out.println("ChildInterface2 - method3 실행");
			}
		};
		
		ci2.method1();
		ci2.method2();
		ci2.method3();
	}
}

/* 출력
ChildInterface1 - method1 실행
디폴트 메서드 method2
ChildInterface1 - method3 실행
ChildInterface2 - method1 실행
디폴트 메서드 by ChildInterface2
ChildInterface2 - method3 실행
*/

 

 


 

 

마지막으로 ChildInterface3를 선언하겠습니다. 이 인터페이스 역시 자신만의 method3( )를 보유합니다. 그런데, 주의할 것이 있습니다. 이 자식 인터페이스는 디폴트 메서드를 추상 메서드로 오버라이드하여 재선언하게 됩니다. 이런 경우에는, 인터페이스 내부에서 method2( )를 추상 메서드로 선언만 해주면 됩니다. 

 

public interface ChildInterface3 extends ParentInterface {
	@Override
	public void method2();
	public void method3();
}

 

이제 이 인터페이스 역시 익명 인터페이스 객체 형식으로 구현을 진행하겠습니다. 결과적으로, 부모 인터페이스의 추상 메서드 method1( ) / 자식 인터페이스가 오버라이드 하여 디폴트 메서드에서 추상 메서드로 전환된 method2( ) / 그리고 자식 인터페이스의 고유 메서드인 method3( )를 모두 오버라이드 해줘야 합니다. 

 

public class ExampleMain {	
	public static void main(String[] args) {
		ChildInterface1 ci1 = new ChildInterface1() {
			@Override
			public void method1() {
				System.out.println("ChildInterface1 - method1 실행");
			}
			
			@Override
			public void method3() {
				System.out.println("ChildInterface1 - method3 실행");
			}
		};
		
		ci1.method1();
		ci1.method2();
		ci1.method3();
		
		
		ChildInterface2 ci2 = new ChildInterface2() {
			@Override
			public void method1() {
				System.out.println("ChildInterface2 - method1 실행");
			}
			
			@Override
			public void method3() {
				System.out.println("ChildInterface2 - method3 실행");
			}
		};
		
		ci2.method1();
		ci2.method2();
		ci2.method3();
		
		ChildInterface3 ci3 = new ChildInterface3() {
			@Override
			public void method1() {
				System.out.println("ChildInterface3 - method1 실행");
			}
			
			@Override
			public void method2() {
				System.out.println("ChildInterface3 - method2 전환실행");
			}
			
			@Override
			public void method3() {
				System.out.println("ChildInterface3 - method3 실행");
			}
		};
		
		ci3.method1();
		ci3.method2();
		ci3.method3();

	}
}

/* 출력
ChildInterface1 - method1 실행
디폴트 메서드 method2
ChildInterface1 - method3 실행
ChildInterface2 - method1 실행
디폴트 메서드 by ChildInterface2
ChildInterface2 - method3 실행
ChildInterface3 - method1 실행
ChildInterface3 - method2 전환실행
ChildInterface3 - method3 실행
*/