코딩항해기

[JAVA] 인터페이스 (+Adapter, 마커인터페이스) 본문

JAVA

[JAVA] 인터페이스 (+Adapter, 마커인터페이스)

miniBcake 2024. 7. 13. 16:12

 

인터페이스

일종의 추상클래스지만 클래스라고 부르지 않으며, 추상화 정도가 높다.

관련 키워드로는 다중상속, 모호성, Adapter, 마커인터페이스 등이 있다.

 

 

 

[요약]

다중상속

java는 다중상속을 지원하지 않지만 인터페이스에 한해 다중구현을 허락하고 있다.

즉, 클래스는 하나의 클래스만 상속가능, 여러 개의 인터페이스를 구현 가능

 

모호성

두 개의 인터페이스에 같은 메서드 시그니처를 가진 메서드 선언 시 모호성 발생 -> 오버라이딩으로 해결

부모클래스와 인터페이스의 메소드가 동일하게 선언 시 모호성 발생 -> 상속 우선 순위가 더 높아 부모 메소드가 사용됨.

 

Adapter 추상클래스

인터페이스의 강제성을 완화시키기 위해 Adapter클래스를 활용

인터페이스(모든 강제성) -[구현]-> 추상클래스(일부구현하여 강제성 낮춤) -[상속]-> 클래스(구현되지 않은 메소드만 구현)

 

마커 인터페이스

클래스들을 그룹화하기 위한 목적으로 사용한다. 어떠한 멤버도 가지고 있지 않다.

 

추상클래스와 인터페이스

  추상클래스 인터페이스
인스턴스화 불가능
접근제한자 가능
추상메소드 가능
일반메소드 가능 불가능
필드 일반 변수, 상수 상수
키워드 extends (상속) implements (구현)

 


 

인터페이스 (Interface)

일종의 추상클래스지만, 클래스라고 부르지 않고 추상화 정도가 높은 것이 특징이다.

인터페이스는 멤버로 상수와 추상메소드만 가질 수 있기 때문에 abstract를 생략할 수 있다.

인터페이스는 객체화 할 수 없으며, 다른 클래스에서 구현(implements)해서 사용한다.

 

 

인터페이스의 선언

interface 인터페이스명{
      //멤버로는 상수, 추상 메소드만 가능하다.
}

 

인터페이스의 모든 변수는 상수로, public static final이다. (생략해도 자동으로 붙음)

인터페이스의 모든 메소드는 추상메소드로, public abstract 이다. (생략해도 자동으로 붙음)

 

 

인터페이스를 사용하는 이유

 1. 여러 클래스에서 선언할 멤버들을 일관되게 관리하기 위해 사용한다. (표준화)

 2. 관계없는 클래스들을 그룹화 시킬 수 있다. (마커 인터페이스)

 3. 클래스 상속과 인터페이스의 구현 클래스는 단일 상속만 가능하며 인터페이스는 다중 구현이 가능하다.

 4. 인터페이스는 인터페이스를 상속할 수 있다. 상속과 구현은 별개이다.

     즉, 하나의 클래스에 상속과 구현을 동시에 할 수 있다.

 


다중 상속(구현)

여러 부모 클래스를 상속하는 것을 다중 상속이라고 한다. java는 모호성 때문에 다중 상속을 지원하지 않는다.

여러 개를 구현할 수 있는 인터페이스 특징 때문에 다중 상속을 지원하는 것이나 다름없다.

public class MiniBcack extends Cake implements Bread, Cream {
	//상속은 단일 상속!
    //구현(인터페이스)은 다중 상속(구현) 가능!
}

 


모호성 (ambiguity) 

다중상속과 관련된 경우에 발생할 수 있다. 다중상속은 한 클래스가 여러 개의 부모클래스로부터 상속받는 것을 의미한다.

모호성은 자식클래스에서 어떤 부모클래스의 멤버를 호출해야할 지 명확하지 않을 때 발생한다.

 

 

모호성 해결방법

두 개의 인터페이스에 같은 메소드(이름, 매개변수, 리턴타입이 같은 메소드) 선언되어있는 경우,

자식 클래스에서 오버라이딩(재정의)하여 사용한다

부모클래스의 메소드와 인터페이스의 디폴트 메소드의 이름과 매개변수가 동일하게 선언되어 있는 경우,
부모클래스의 메소드가 사용된다. 구현하는 인터페이스보다 상속받는 부모클래스의 우선순위가 더 높기 때문이다

 


Adapter 추상클래스 

인터페이스는 강제성이 강하기 때문에 구현하는 클래스에서 일부만 재정의하여 사용하는 것이 불가능하다.

이를 해결하기 위해서 Adapter 추상클래스를 활용한다.

Adapter 추상클래스를 활용해 interface의 강제성을 낮추는 방법을 설명하는 이미지

 

Adapter클래스는 인터페이스의 강제성을 완화시키기 위해 사용한다.

어댑터 클래스는 추상 클래스로 만들기 때문에 미구현된 메소드(추상 메소드)와 구현된 메소드가 동시에 존재할 수 있다.

그러므로 어댑터 클래스에서 인터페이스를 상속받아 강제성을 없애고 싶은 메소드만 재정의(오버라이딩)해준다.

이후 어댑터 클래스를 상속시키면, 상속받는 자식 클래스는 구현되지 않은 메소드만 재정의(오버라이딩) 할 수 있다.

이 때 어댑터 클래스의 이름은 이름 뒤에 Adapter를 붙여주어 목적을 알려주는 것이 좋다.

 


마커 인터페이스 (Marker Interface)

클래스들을 그룹화하기 위한 목적으로 사용한다.

서로 다른 클래스들을 공통되는 타입을 갖도록 하는 것이 유일한 목적이기 때문에,

마커 인터페이스는 어떤 멤버도 선언하지 않는다.

 

마커인터페이스

package markerTest;

public interface MarkerInterface {
//마커인터페이스는 어떤 멤버도 선언하지 않는다
}

 

마커인터페이스를 구현한 SomeClass  클래스 

package markerTest;

public class SomeClass implements MarkerInterface{
	//필드
	//생성자 (매개변수)
	//메소드
}

 

instanceof를 통해 해당 클래스가 어떤 부모 클래스를 가지고 있는지 확인할 수 있다.

이러한 기능들을 통해 클래스들을 그룹화할 수 있다.

package markerTest;

public class MarkerInterMain {
   public static void main(String[] args) {
      SomeClass sc1 = new SomeClass("데이터");
      
      if(sc1 instanceof MarkerInterface) {
         System.out.println("sc1은 MarkerInterface를 구현한 클래스 입니다");
      }else {
         System.out.println("sc1은 MarkerInterface를 구현하지 않은 클래스 입니다");
      }
   
   }
}

 

 

마커 인터페이스 활용 예시

public class Main {
	public static void main(String[] args) {
		Main m = new Main();
		m.checkA(new Carnivore());
		m.checkA(new Eagle("독수리"));
		m.checkA(new Tiger("호랑이"));
		m.checkA(new Horse("말"));

		Animal[] animals = { new Eagle("독수리"), new Tiger("호랑이"), new Horse("말") };
	}

	void checkA(Animal animal) {
		if (animal instanceof Carnivore) {
			System.out.println(animal.getName() + "은/는 육식동물입니다");
		} else if (animal instanceof Herbivore) {
			System.out.println(animal.getName() + "은/는 초식동물입니다");
		}
	}

	void checkB(Animal[] animals) {
		for (int i = 0; i < animals.length; i++) {
			if (animals[i] instanceof Land) {
				System.out.println(animals[i].getName() + "은/는 뛰어다닙니다");
			} else if (animals[i] instanceof Sky) {
				System.out.println(animals[i].getName() + "은/는 날아다닙니다");
			}
		}
	}

}

 

 


추상클래스와 인터페이스 비교

  추상클래스 인터페이스
인스턴스화 불가능하다.
접근제한자 접근제한자를 가질 수 있다.
추상메소드 추상메소드를 가질 수 있다.
일반메소드 일반메소드를 가질 수 있다. 일반메소드를 가질 수 없다.
필드 일반 변수, 상수를 가질 수 있다. 상수만 가질 수 있다.
키워드 extends (상속) implements (구현)

 

'JAVA' 카테고리의 다른 글

[JAVA] 컬렉션 프레임워크 (+Generic, Iterator)  (0) 2024.07.15
[JAVA] 연산자  (0) 2024.07.14
[JAVA] 자바 프로그래밍의 기초  (0) 2024.07.12
[JAVA] 다형성  (0) 2024.07.07
[JAVA] Up casting, Down casting  (0) 2024.07.04