본문 바로가기

Language/Java

[JAVA] Interface (인터페이스)

1. 인터페이스란? 

'클래스를 어떻게 만들어라'는  가이드 라인이다. 

오로지 상수(static final로 선언된 변수)와 추상 매소드로만 이루어져 있다. 

해당 인터페이스를 '구현' 한 클래스는 추상 매소드 전부를 구체화할 의무를 가진다.

 

* 선언 

interface 인터페이스 이름 {
상수 or 추상매소드

}


//EX)
public interface Animal {
	public abstract void cry(); //public abstract는 안 써도 됨. -> default로 되어있음 
}

 *상속 or 구현 

인터페이스 끼리 확장할 때는 상속(extends) 키워드를 사용한다. 클래스가 특정 인터페이스를 받아서 구체화될 떄는 구현(implements) 키워드를 쓴다. 

// 인터페이스로 확장
public interface Pet extends Animal {

	//같은 인터페이스 이므로 구체화 x 
    public abstract void cry();
    
}
// 클래스로 받을 때
public class Dog implements Pet {
	public void cry(){
    	System.out.println("멍 멍"):
    }
}

인터페이스는 클래스에 장착하는 부품 같은 것이다. 따라서 어떤 부모 클래스를 상속하는 자식 클래스에도 장착할 수 있다. 

public class Poketmon_2G extends Poketmon_1G implements newEngine, NintendoSwitch {
	// 포켓몬 1세대로부터 상속받은 내용
    
    // newEngine, 닌텐도 스위치 내용도 구현 

}

(1) 인터페이스의 장점 : 중복 상속이 가능하다. (클래스와의 차이점)

추상클래스는 저번 포스팅 설명과 같이, 완성되지 않은 클래스를 뜻한다. 

따라서 추상클래스는 추상매소드를 포함하지만, 일반 매소드, 상수, 변수 모두 포함할 수 있다. 

하지만 인터페이스는 오로지 상수와 추상매소드만 포함할 수 있다. 

 

그렇다면 인터페이스란 클래스 가이드 라인을 왜 만들었을까? 

우리가 클래스를 만들다보면, 다수의 클래스를 한번에 상속받아 쓰고 싶은 상황이 생긴다.

예를 들어 반려동물이라는 클래스가 반려동물의 울음소리를 표현하는 매소드를 가진다고 가정하자. 이 경우 울음소리를 동물 별로 일일히 만들기 보단, 다수의 동물 클래스를 상속받아, super.cry();로 쉽고 간결하게 표현하고 싶을 수 있다.  하지만 클래스는 중복 상속이 불가능하다. 

왜냐하면 매소드 호출의 모호성이 생기기 때문이다. 

예를 들어 설명하겠다. 

위의 예에서 이어서, 반려동물 클래스 안에 고양이와 강아지의 울음소리를 둘다 표현 하고자 한다. 고양이와 강아지 각각 울음소리 기능을 가진 클래스가 존재한다고 하면, 

// class로 중복 상속한 경우 
public class Dog{
	public void cry(){
    	System.out.println("멍 멍");
	}
}

public class Cat{
	public void cry(){
		System.out.println("아옹 까옹")
	}
}


public Pet extends Dog,Cat {
	
    public void cry(){
    // 해당 super가 지칭하는 부모 클래스는 누구지? 어떤 클래스의 매소드를 호출한 것이지?
    	super.cry();
    }
}

위와 같이 자식 클래스에서 부모 클래스의 매소드를 호출할 때, 두 매소드의 이름이 같은 경우, 호출한 매소드가 누구인지 모호하다. 이것을 매소드 호출의 모호성이라 생긴다. 

추상 클래스는 추상 매소드가 있어서 더 나을 것이라 생각할 수 있지만, 추상 클래스도 똑같이 일반 매소드와 변수를 가질 수 있는 입장에서 매소드 호출의 모호성에서 자유롭지 않다. 

따라서 Java는 클래스의 중복상속을 금지한다. 

하지만 중복 상속은 여전히 이점이 있다. 상속 관계를 통해 해당 클래스의 속한 내용이 뭔지 빠르게 파악이 가능하다는 점에서 코드의 가독성을 높여준다. 

Java에서는 중복 상속의 이점을 이용하기 위해 인터페이스를 사용한다. 

인터페이스를 이용하면 매소드 호출의 모호성이 생기지 않아, 중복 상속을 사용할 수 있다. 

public interface Dog {
	void cry();
}

public interface Cat {
	void cry();
}

public class Pet implements Dog, Cat {
	public void cry(){
    	System.out.println("멍 멍, 냐옹 냐옹");
    }
}

구현 자체는 클래스에서만 하므로, 매소드 호출의 모호성이 일어나지 않고, 우리는 구현한 인터페이스가 뭔지만 봐도 해당 클래스에서 구현한 내용이 무엇인지 빠르게 파악할 수 있다. (여기서는 인터페이스 별로 매소드가 하나여서 와닿지 않지만, 인터페이스 별로 매소드가 다르고, 많은 경우를 상상해봐라.)

 

2. 코드 해설

수업 내용에 대해서 해설 하겠다. 

먼저 수업에서는 Detectable과 Reportable이라는 인터페이스를 각 각 만들었다. 

public interface Detectable {
    void detect(); // 화재 감지
}


public interface Reportable {
    void report(); //신고 기능

}

해당 인터페이스를 클래스로 구체화 하였다. 여기까지는 사전 준비 이다.

public class AdvancedFireDetector implements Detectable{
    @Override
    public void detect() {
        System.out.println("향상된 성능으로 화재를 감지합니다.");
    }
}


public class VideoReporter implements Reportable{

    @Override
    public void report() {
        System.out.println("직전 30초 영상과 함께 신고를 진행합니다.");
    }
}

이제 진짜 사용할 클래스를 나타내겠다

// 인터페이스의 내용(detect, report 매소드 구현 필요, Camera 부모 클래스의 추상 매소드도 구현 필요)
public class FatoryCam extends Camera implements Detectable, Reportable {


	//해당 변수들은 인터페이스의 추상 매소드 오버라이딩을 위해 필요하다.
    //매개체 역할
    private Detectable detector;

    private Reportable reporter;

    // 인수로 받은 Detectable 자료형의 객체를 인스턴스 변수의 값으로 받겠다.
    // 해당 변수를 이용해 내 추상 매소드를 구체화 하겠다.
    public void setDetector(Detectable detector) {
        this.detector = detector;
    }

    public void setReporter(Reportable reporter) {
        this.reporter = reporter;
    }



	// 부모 클래스의 추상 매소드
    @Override
    public void showMainFeature() {
        System.out.println("화재 감지");
    }

    // 인수로 들어온 객체의 매소드가 내 추상 매소드의 내용 
    @Override
    public void detect() {
        detector.detect();
    }

    @Override
    public void report() {
        reporter.report();
    }
}

 

main 매소드

public class _02_Interface {
    public static void main(String[] args) {


//객체 생성
        VideoReporter videoReporter = new VideoReporter();

//객체 생성
	Detectable advancedFireDetector = new AdvancedFireDetector();

// 객체 생성
		FatoryCam fatoryCam = new FatoryCam();
        
// 클래스 내 추상 매소드를 같은 인터페이스를 사용한 객체로 구체화 하겠다. 

	fatoryCam.setDetector(advancedFireDetector);
        fatoryCam.setReporter(videoReporter);

        fatoryCam.detect();
        fatoryCam.report();
    }
}

 

*점검

인터페이스란? 

무엇으로 이루어져 있지? /

추상 클래스와의 차이점(구성요소, 중복상속 관련)

'Language > Java' 카테고리의 다른 글

[JAVA] Generic Class  (0) 2023.02.03
[JAVA] Generics  (0) 2023.02.02
[JAVA] 추상화와 추상화 클래스  (0) 2023.02.01
[JAVA]열거형  (0) 2023.01.29
[JAVA]final  (0) 2023.01.29