[JAVA] 인터페이스

나의 개발 일지·2024년 11월 25일

JAVA

목록 보기
4/11

💡인터페이스(Interface)

인터페이스란?

이전 포스팅에서 '추상 클래스'에 대해 알아보았고, 순수 추상 클래스는 클래스를 이루는 모든 메서드가 추상 메서드인 추상 클래스를 의미한다. 인터페이스는 순수 추상 클래스를 더 편리하게 사용가능한 기능이다.

순수 추상 클래스

// 순수 추상 클래스
public abstract class AbstractAnimal {
	public abstract void sound();
    public abstract void move();
}
  • 인스턴스 생성 불가능
  • 상속시 모든 메서드를 overriding 해야한다
  • 주로 다형성을 위해 사용

인터페이스

인터페이스는 abstract가 아닌 interface 키워드를 사용하면 된다. 또한, 인터페이스는 public abstract 키워드의 생략이 가능하고 권장된다.

public interface InterfaceAnimal {
	void sound();
    void move();
}
  • 인터페이스는 순수 추상 클래스와 같다
  • 메서드는 모두 추상 메서드인데, public abstract 키워는 생략 가능하고, 권장된다
  • 인터페이스는 다중 상속(구현)이 가능하다

인터페이스와 멤버변수

public interface InterfaceAnimal {
	// public static final double MY_PI = 3.14;
    double MY_PI = 3.14;
}

인터페이스에서 멤버변수는 '상수'이다. 또한 인터페이스의 상수는 메서드와 동일하게 public static final이 생략이 가능하고 권장된다.

예제

public interface InterfaceAnimal {
	void sound();
    void move();
}

public class Dog implements InterfaceAnimal {
	@Override
    public void sound() {
    	System.out.println("멍멍");
    }
    
    @Override
    public void move() {
    	System.out.println("개 이동");
    }
}

public class Cat implements InterfaceAnimal {
	@Override
    public void sound() {
    	System.out.println("냐옹");
    }
    
    @Override
    public void move() {
    	System.out.println("고양이 이동");
    }
}

public class Cow implements InterfaceAnimal {
	@Override
    public void sound() {
    	System.out.println("음메");
    }
    
    @Override
    public void move() {
    	System.out.println("소 이동");
    }
}
// -----------------------------Main Method----------------------------------

public class InterfaceMain {
	public static void main(String[] args) { 
    	
        // 인터페이스 생성 불가
        // InterfaceAnimal interfaceMain1 = new InterfaceAnimal();
        
        Cat cat = new Cat();
        Dog dog = new Dog();
        Caw caw = new Caw();
        
        soundAnimal(cat);
        soundAnimal(dog);
        soundAnimal(caw);
        
    }
    
    private static void soundAnimal(InterfaceAnimal animal) {
    	System.out.println("동물 소리 테스트 시작");
        animal.sound();
        System.out.println("동물 소리 테스트 종료");
    }
}

위의 예제를 보면 인터페이스와 순수 추상 클래스의 차이점이 거의 없음을 알수있다. 실제로 메모리 구조상 클래스, 추상 클래스, 인터페이스의 차이는 없다.

인터페이스, 왜 사용할까?

형태만 보면 인터페이스는 abstract키워드만 사용하지 않을 뿐 순수 추상 클래스와 동일한 기능을 한다. 그렇다면 왜 순수 추상 클래스를 사용하지 않고 인터페이스를 사용해야할까?

  • 제약

    • 인터페이스는 '반드시 구현해야한다'라는 제약사항이 있다. 즉, 인터페이스안의 메서드는 반드시 순수 추상 메서드 형태이어야하고 자식 클래스는 반드시 해당 메서드를 오버라이딩 해야한다. 순수 추상 클래스와의 차이점은 순수 추상 클래스는 미래 특정 시점에 순수 추상 메서드가 아닌 일반 메서드를 추가하여 일반 추상 클래스로의 전환 가능성이 있다는 점이다. 인터페이스를 사용하여 이런 점을 원천 방지가 가능하다
  • 다중구현

    • java에서 클래스 상속은 하나의 부모에게서만 가능하다. 하지만 인터페이스의 경우 자식 입장에서 여러 인터페이스로부터 상속이 가능하다.

상속 vs 구현

부모 클래스의 기능을 자식 클래스가 상속 받을 때, 클래스 상속이라고 표현한다. 하지만 부모 인터페이스의 내용을 자식 클래스가 상속 받을 때는 클래스 '구현'이라고 표현한다. 인터페이스는 모든 메서드가 순수 추상 메서드 즉, 본문이 전혀 없는 메서드이다. 따라서 부모 인터페이스로부터 물려받을 기능은 존재하지 않고 오히려 자식 클래스에서 이를 오버라이딩하여 기능을 '구현'해야한다. 따라서 인터페이스를 '구현'한다고 표현한다.

인터페이스의 다중 구현

다이아몬드 문제


만약 위의 그림과 같이 AirplaneCar클래스가 Airplane, Car 두 개의 부모 클래스로 부터 다중 상속을 받는다고 가정하자. 두 개의 부모 클래스에는 모두 move() 메서드가 존재하고 이를 자식 클래스에서 사용하려고 한다면 어떤 부모의 메서드를 사용해야할까? 이를 다이아몬드 문제라고 하고, 이러한 이유로 다중 상속은 허용되지 않는다. 하지만 인터페이스의 다중 구현을 통해 이러한 문제를 피하고 구현 가능하다.


InterfaceA, InterfaceB는 모두 methodCommon()을 갖는다. 자식 클래스인 Child 입장에서는 두 인터페이스를 구현해야하는데, 상속의 경우 두 부모 클래스의 methodCommon()중 어떤 메서드를 사용할 것인가의 다이아몬드 문제가 발생한다. 하지만 인터페이스의 메서드는 기능을 가지지 않기에 해당 인터페이스를 구현하는 자식 클래스에서 해당 기능을 구현해야한다. 즉, InterfaceA, InterfaceB는 모두 methodCommon()을 제공하지만 최종구현은 Child에서 구현되어야 하며, 오버라이딩에 의해 호출도 Child의 methodCommon()이 우선 호출되기에 다이아몬드 문제가 발생하지 않는다.

0개의 댓글