[Java] 자바 인터페이스(Interface) 알아보기

2020-12-01


인터페이스는 자바에서의 다형성을 실현하기 위해 객체의 교환성을 높여주는 역할을 한다. 선언 방법으로는 아래와 같이 New -> Interface를 선택해서 간단히 생성할 수 있다.


인터페이스의 특징으로는 상수와 메소드만 선언 가능하며, 생성자를 가질 수 없다. 또한 메서드는 추상 메서드 / 정적 메서드 / 디폴트 메서드 3가지 종류로 나누어진다. 이 중에서 추상 메서드를 사용하려면, 이를 구현하는 구현 클래스가 따로 필요하다.(위의 인터페이스는 추상 메서드 2개를 선언해 두었다.)

 

아래는 구현 클래스에 대한 내용이다.

package interfacePractice;

public class move implements arm1, arm2, body{
	// 구현하는 모든 인터페이스의  추상메소드를 정리해야지 사용 가능하다.
	@Override
	public void up1() {
		System.out.println("왼팔을 올립니다.");
	}
	
	@Override
	public void down1() {
		System.out.println("왼팔을 내립니다.");
	}
	
	@Override
	public void up2() {
		System.out.println("오른팔을 올립니다.");
	}
	
	@Override
	public void down2() {
		System.out.println("오른팔을 내립니다.");
	}
	
	@Override
	public void act() {
		System.out.println("움직입니다.");
	}
	
}

 

구현 클래스를 생성시에는 클래스명 뒤에 implements를 선언하여, 자신이 어떤 인터페이스를 구현하는지에 대하여 명시해야 한다. 여기서 중요한 점은 implements로 선언된 각 클래스들의 추상 메서드를 하나도 빠짐없이 모두 구현 클래스에 Override 해서 재정의 해주지 않으면, 컴파일에서 오류가 발생한다.

 

(아래는 나머지 arm2와 body에 대한 코드이다. 모두 추상 메소드만 선언해 주었다.)

package interfacePractice;

public interface arm2 {
	public void up2();
	public void down2();
}
package interfacePractice;

public interface body {
	public void act();

}

다음은 디폴트 메서드와 정적 메서드를 구현한 인터페이스이다.

package interfacePractice;

public interface top {
	public void think();
	
	public default void speak (int a){
		if(a < 10) {
			System.out.println("그 숫자는 저에게 조금 작군요.");
		}else {
			System.out.println("그 정도면 적당한 숫자인거 같네요.");
		}
	}
	
	public static void speak2() {
		System.out.println("나는 사람이다.");
	}
	
}

우선 디폴트 메서드를 살펴보자 기존 추상 메서드와 다른 점은 객체를 전달받는 점과 / 인터페이스에서 선언된다는 점에서 차이가 있다. 다만 아무리 인터페이스에서 해당 내용이 선언된다고 하여도 구현 객체가 필요하며, 인터페이스 내부에서는 실행될 수가 없고, 실행(main) 클래스 사용하여야 한다. (디폴트 메서드도 Override가 가능하다.)

 

정적 메서드의 경우에는 static의 성질을 가지고 있어, 인터페이스임에도 불구하고 구현 클래스 없이 바로 사용이 가능하다는 특징을 가지고 있다.

 

아래는 top 인터페이스의 구현 클래스이다.

package interfacePractice;

public class think implements top {
	@Override
	public void think() {
		System.out.println("생각합니다.");
	}
}

(중요한 점은 디폴트 메서드는 구현 클래스만 필요할뿐 따로 재정의 해줄 필요는 없어, 추상 메서드만 재정의 해주었다.)


이제 main(실행클래스)으로 가서 실행을 시켜보도록 하자. 

package interfacePractice;

public class main {

	public static void main(String[] args) {
		
		top t = new top() {
			public void think() {
				System.out.println("익명 구현 개체는 구현클래스를 사용하지 않고 일회성 사용");
			}
		};
		t.think();

위의 코드는 익명객체를 생성해서 추상 메서드를 사용하는 방법이다. 이는 구현 클래스를 만들지 않고 바로 실행 클래스에서 사용하는 방법으로, 일회성으로 사용하는 경우에 유용하다. 실행결과 역시 정상적으로 출력된다.


package interfacePractice;

public class main {

	public static void main(String[] args) {
				
		move m = new move();
		m.act();
		m.up1();
		m.up2();
		m.think();
		m.speak(5);
		m.speak(14);
		top.speak2(); // 인터페이스있는 정적클래스 바로 사용 가능

(기존에 arm1 / arm2 / body의 인터페이스를 구현하던 move 클래스에 think(구현클래스)를 상속받았다.)

실행 클래스에서의 선언은 기존의 다른 클래스를 새로운 객체로 선언하는 것과 다른 점은 없다. 구현 클래스 move를 m이라는 새로운 객체를 만들어 각각의 메서드를 실행해 보았다. 정상적으로 Console 창에 구현 클래스에서 정의한 내용들이 출력되는 것을 확인할 수 있다. (top.speak2는 정적 메서드 -> 인터페이스를 직접 불러내 사용)