1. 인터페이스 다중 구현

 

인터페이스는 다중 구현이 가능하다. 클래스와 다른 점이다. extends 키워드는 한개의 클래스만 가능하지만 implements 키워드는 여러개의 인터페이스를 구현할 수 있다. 물론 인터페이스는 구현이 된 상태가 아니지만, 클래스와 인터페이스의 차이점은 계속 보게 될 것이다.

 

public class ITest{
	
	public static void main(String[] args) {
		InterEX e1 = new InterEX();
		
		A a1 = e1;
		a1.A();
		// a1.B();
		
		B b1 = e1;
		b1.B();
		//b1.B();
		
		if(a1 instanceof InterEX) {
			InterEX e2 = (InterEX)a1;
			e2.A();
			e2.B();
		}
	}
}

class InterEX implements A,B{
	@Override
	public void B() {
		System.out.println("B implemented");
	}
	@Override
	public void A() {
		System.out.println("A implemented");
	}
}
interface A{
	void A();
}
interface B{
	void B();
}

 

위의 예제에서는 interface를 2개 구현하고 있다. 2개를 구현한 클래스는 2개의 추상메소드를 완전히 구현해야 인스턴스화 할 수 있다.

 

main 메소드를 보자. 인터페이스를 구현한 InterEX클래스를 생성한다.

 

클래스의 묵시적 형변환 처럼 e1을 A 인터페이스와 B 인터페이스의 참조에 할당할 수 있다. 그림을 보면 다음과 같다.

 

 

 

A, B, InterEX 각각의 구역이 정해져있고, 참조변수가 누구냐에 따라 접근권한에 차이가 난다.

 

main 메소드의 if절을 보자. instanceof 키워드로 인스턴스가 맞는지 확인을 한다. A형 참조변수를 하위클래스로 다운캐스팅 한다. 하위클래스의 참조변수로 갔으니까 이제 A와 B 인터페이스 두개 다 메소드에 접근할 수 있게 된다.

 

 

자바 튜토리얼 (8-5) instanceof 키워드, 다운캐스트 형변환

클래스는 객체의 멤버 변수와 메소드를 정의해 놓은 것이고 인스턴스는 클래스가 실제 메모리에 생성된 상태이다. 자바의 다형성에서 상위클래스의 참조변수로 하위클래스의 인스턴스를 사용�

digiconfactory.tistory.com

약간 복잡하게 보이지만 실리콘밸리 출신 프로그래머 알 스웨이가트의 말처럼 "코딩은 수학이 아니다. 오히려 블록 쌓기같은 게임에 가깝다."는 말처럼 상위(위) 하위(아래)를 왔다리 갔다리 하고 있다.

 

2. 다중 구현 인터페이스의 메서드 중복

이런 경우다. A와 B인터페이스에 둘다 default 로 void C가 구현되있다. 동일한 이름에 다른 내용이다. 이럴때 컴파일러는 뭐라고 할까?

 

위 에러메시지 처럼 void C 메소드를 오버라이드 하라고 한다. 어느쪽을 오버라이드 하는가는 차이는 있다. 이클립스로 생성하면 정확한 위치를 알려준다.

패키지가 com.kay.inter 이고 A인터페이스에 있는 하위클래스에서 보면 super 부모의 .C( ) 메소드이다. 오버라이드는 하나밖에 없으니까 결과는 같을 것이다.

 

3. 인터페이스 상속

인터페이스 간 상속이 가능하다. 인스턴스를 만들 수는 없지만 상속관계를 가질 수 있다. 일반 클래스와 차이는 여러개의 인터페이스를 상속할 수 있다.

 

인터페이스 A는 C와 D로부터 상속받는다. 인터페이스라서 다른 추상메소드들은 구현할 필요가 없다. 다만 default 메소드는 구현해줘야한다. A와 B간에 충돌이 있기때문에 다음 클래스에서는 정리해줘야 한다. 상속은 받았지만 인스턴스는 다음 하위클래스에서 만들어 줘야한다.

 

main 메소드에서 클래스를 인스턴스로 만든다. 상위 인터페이스로 형변환 하면 역시 그 인터페이스의 메소드들에만 접근할 수 있다.

 

이것을 중간의 C인터페이스로 형변환 할 수가 있다. 그러면 A와 B의 메소드들을 다 사용할 수 있다. 인스턴스는 NewClass에서 만들고 오버라이드도 여기서 했지만 사용은 C에가서 할 수도 있다. 물론 인스턴스가 NewClass이기 때문에 C의 인터페이스 내용을 참조하는 것은 아니다. 그래서 인스턴스를 어디서 만들었는가가 중요하다.

 

public class ITest{
	
	public static void main(String[] args) {
		NewClass nc1 = new NewClass();

		A a1 = nc1;
		a1.A();
		// a1.B();
		
		B b1 = nc1;
		b1.B();
		//b1.B();
		C c1 = nc1;
		c1.A();
		c1.B();
		c1.C();
		c1.D();
	}
}
interface A{
	void A();
	default void C() {
		System.out.println("A interface C");
	}
}
interface B{
	void B();
	default void C() {
		System.out.println("A interface B");
	}
}

interface C extends A,B{
	void D();
	@Override
	default void C() {
		System.out.println("interface C extends A,B");
	}
}
class NewClass implements C{

	@Override
	public void A() {
		System.out.println("This is new class method A");
	}

	@Override
	public void B() {
		System.out.println("This is new class method B");
	}

	@Override
	public void D() {
		System.out.println("This is new class method D");
	}
}

인터페이스 챕터는 여기까지 포스트하도록 하겠다. 솔직히 보이지 않는 개념들을 가지고 머리속에서 블록쌓기를 하려니 힘이 들 수도 있다. 인터페이스는 그보다 깊고 넓은 세계이다. 객체지향을 배운다는 생각으로 한개씩 접근해 나가면 좋을 것 같다.

 

실무의 프레임워크는 거의 클래스와 인터페이스로 제공된다. 즉 다른 사람이나 기업에서 이미 기능을 만들어 놓은 경우가 많다는 것이다. 나만의 인터페이스를 개발하려면 남의 것들을 유심히 살펴봐야한다. 모방은 창조의 어머니라고 그러지 않았던가. 많은 프레임워크를 다뤄보면서 거기서 내가 필요한 방법론을 취하는 것도 하나의 방법이다.

공유하기

facebook twitter kakaoTalk kakaostory naver band