본문 바로가기

프로그래밍 언어 기초/JAVA

Chapter 11. 인터페이스(Interface)

11. 1. 인터페이스(Inteface)?

인터페이스(Inteface)는 무엇일까요? 표준국어대사전에서 그 의미를 찾아보면 아래와 같습니다.

 

 

 쉽게 이해하려고 사전을 펼쳐 보았지만, 정의가 어려워서 더 이해가 되지 않는 것 같습니다. 인터페이스의 쉬운 사례를 생각해보면 UI라는 단어를 생각해보시면 될 것 같습니다. UIUser Interface라는 단어의 약자이죠. 어라? 여기에도 Interface라는 단어가 있네요. 그런데, 우리가 UI라고 한다면 어떤 것이 떠오르시나요? 예쁘게 잘 만들어진 버튼이나 글씨들 화려한 애니메이션으로 사용자의 시선을 뺏는 웹사이트 등이 생각나지 않으신가요? 네 맞습니다. 이것들 또한 인터페이스의 일종으로 여기서 유추해보자면 인터페이스는 사용자와 컴퓨터를 이어주는 버튼 같은 건가? 하고 생각이 드실 것 같습니다. 바로 여기서 인터페이스의 정의를 다시 볼까요? ‘서로 이어주는 부분, 또는 그런 접속장치란 바로 이런 것을 의미하는 것입니다.

 

 사실 개발자들이야 내부에 코드가 어떻게 효율적으로 작성되고 이쁘게 되어 있는지 궁금하지 일반인은 그런 부분보다 솔직히 잘 작동하면 장땡이라는 생각이 더 지배적이죠? 이처럼 내부에 얼마나 훌륭한 코드가 있는지 몰라도 사용자나 혹은 개발자가 쉽게 사용할 수 있도록 이어주는 것을 인터페이스라고 할 수 있겠습니다.

 

자바의 인터페이스도 이러한 역할을 합니다. 다른 개발자들이 내부에 어떤 로직을 가지는지 자세히 알지 않아도 쉬이 가져다가 새롭게 재정의해서 쓸 수 있도록 하는 역할을 해줍니다. 일반 사용자에게는 버튼 같은 것으로 제공했다면 우리 개발자들에게는 코드로 제공해주는 것이죠.

 

인터페이스의 선언

public interface Interface { // interface는 class 대신 interface 키워드를 사용해 선언한다!
	
	// 인터페이스의 멤버변수(필드)는 모두 public static final 이며 생략 가능.
	public static final int PID = 123;
	int codeNumber = 13; // 생략됨.
	
	// 모든 메소드는 public abstract 가 생략된 형태.
	public abstract void method1();
	void method2();
    
}

 

 

 인터페이스는 최고 수준의 추상화 단계라고 말합니다. 인터페이스는 추상 클래스의 더 진보된 형태라고도 볼 수 있으며 모든 메소드는 전부 abstract입니다. 하지만 작성하지 않죠. 이 또한 훌륭한 자바의 개발자분들이 다른 개발자들이 어차피 똑같이 abstract를 작성해야 하는 부분이니 이런 부분을 그냥 생략해서 편히 쓸 수 있도록 해준 세심한 배려라고 할 수 있죠.

 

 하지만 인터페이스가 이 정도라면 별로 임팩트가 없겠죠? 인터페이스의 진가는 사실 따로 있었습니다. 바로 인터페이스는 자바 상속의 단점을 극복할 수 있습니다! 무슨말이냐고요? 인터페이스는 자바의 단일 상속의 단점을 극복할 도구가 될 수 있다는 말입니다.

 

 

인터페이스의 상속

import com.tstory.chap6.Parent;

public class InterfaceImpl extends Parent implements Interface {
	// 부모 클래스의 상속과 인터페이스의 상속은 동시에 가능하다!
		
	// 인터페이스의 메소드는 바디가 없었기 때문에 상속받은 클래스에서
	// 내부 로직을 직접 구현하여 사용한다.
	// 부모 클래스 상속과 인터페이스 상속이 동시에 이루어 졌다면 인터페이스의 구현부에서 부모 클래스의 필드에도 접근 가능하다! 
	@Override
	public void method1() {		
		System.out.println("HELLO WORLD! :"+super.id);		
	}

	@Override
	public void method2() {
		System.out.println("HELLO WORLD !"+super.password);
		
	}
	
}

 

 인터페이스 테스트

public class InterfaceTest {
	
	public static void main(String[] args) {
		
		// Interface if1 = new Interface(); // 인터페이스는 추상클래스의 진보된 형태이므로 인스턴스를 생성할 수 없다.
		// 하지만 Interface를 상속받은 클래스의 자료형으로는 사용 가능하다.
		Interface if2 = new InterfaceImpl();
		if2.method1();
		if2.method2();
		
		// 자기 자신을 자료형으로 하는 것도 당연히 가능!
		InterfaceImpl if3 = new InterfaceImpl();
		
	}

}

 

  자바에서는 이미 작성된 메소드를 가져다 쓰는 것을 상속(Inheritance)을 통해서 했습니다. 하지만 자바의 상속은 단일 상속으로 엄격히 제한했기 때문에 여러 클래스를 사용할 순 없었죠. 그래서 자바 상속의 관계는 영어로 표현하면 ‘ is ’ 관계라고 합니다. 사과는 과일이다(Apple is Fruit)처럼 의미상 종속적인 관계가 성립될 때, 상속을 사용하게 되고 is 관계라고 합니다. 반면, 사람은 동물이다, is 관계이죠? 그런데, 사람은 컴퓨터를 사용할 수 있어서 사람 클래스에 컴퓨터를 상속시켜보았습니다. 그러면 사람은 컴퓨터다. 말이 이상하죠? 사람은 컴퓨터를 가지고 있다. 이렇게 표현하는 게 더 맞을 거 같습니다. 이렇듯이 의미상 종속적인 관계가 아닌 소유의 관계를 갖는 경우를 ‘has’ 관계라고 하고 이 때 인터페이스가 사용됩니다. 왜냐하면, 인터페이스는 다중 상속이 가능하기 때문이죠. 또한 인터페이스는 클래스를 상속할 때 쓰는 키워드 extends를 사용하지 않고 implements를 사용하며 여러 개를 상속할 수 있는 장점이 있습니다.

 

마침내 자바 개발자도 하나의 클래스에 여러 클래스를 사용하여 맥가이버 클래스를 만들 수 있게 된 것입니다. 참 멋지죠?

 

 마지막으로 JDK 1.8부터는 인터페이스에 default method라는 것이 추가되었습니다. 이것을 이용하면 인터페이스에서 직접 내부 로직을 작성할 수 있게 되었습니다. 이것이 추가된 이유는 프로그램의 업데이트와 관련이 있습니다. 자바라는 언어도 옛것을 그대로 사용하는 것이 아니라 시간이 지날수록 개발자들의 편의에 맞추어 여러 강력한 기능들을 추가하게 되는데요. 이때마다 기능이 추가되면 실제 운용되고 있는 모든 클래스 들에서 동시다발적으로 컴파일 오류가 발생하고 시스템을 불안정하게 만든다면 참 곤란하겠죠? 그래서 JDK 1.8 이후부터는 인터페이스에 default method를 추가하여 인터페이스인데도 불구하고 구현을 강제하지 않고 구현을 개발자의 자율에 맡기는 문법이 추가 되었습니다.

 

default method의 선언

public interface Interface {
		
	// JDK 1.8 이후에 등장한 default 메소드!
	// 원래 인터페이스에는 구현부가 없었으나, 
	// 구현부가 있는 default 메소드가 등장하면서 기존의 이름이 동일한 메소드들과 충돌이 발생
	// 그래서 우선순위가 성립하게 되었고, default 메소드와 충돌이 발생하면 super class의 메소드가 우선함
	// 인터페이스 간에 충돌이 발생하면, 원래 default 메소드는 Override를 하지 않아도 되지만 반드시 Override를 해주어야 함.
	default void method3() {
		System.out.println("DEFAULT 메소드 입니다!");
	}	
}

 

default method의 구현

import com.tstory.chap6.Parent;

public class InterfaceImpl extends Parent implements Interface {
	// 부모 클래스의 상속과 인터페이스의 상속은 동시에 가능하다!
	
	// default 메소드는 구현을 강제하지 않으므로 작성하지 않아도 컴파일 오류 X
//	@Override
//	public void method3() {
//		
//	}

}

 

default method 테스트

public class InterfaceTest {
	
	public static void main(String[] args) {
				
		Interface if1 = new InterfaceImpl();
		if1.method3(); // 구현하지 않았어도 default 메소드는 사용 가능!
	}

}

 

 

 

참고문헌

인터페이스 : https://ko.dict.naver.com/#/entry/koko/780e996aabb748788158079de5b19d4c