강의와 도서/자바의 정석 3편

Chapter 7-7. 인터페이스

Tech_JINI 2025. 1. 10. 18:02

인터페이스: 추상 메서드의 집합

 

인터페이스의 구현 = 인터페이스의 추상메서드 몸통{} 만들기(미완성 설계도 완성하기)

 

abstract class Player {
    abstract void play(int pos);
    abstract void stop();
}

class AudioPlayer extends Player {
	void play(int pos){내용생략} 
    void stop() {내용생략}
}

-> 추상 클래스의 구현

미완성 설계도 Player을 상속하여 설계도를 완성시킴

 

interface Fightable {
    void move(int x, int y);
    void attack(Uniy y);
}

class Fighter implements Fightable {
	public void move(int x, int y){내용 생략};
    public void attack(Unit u){내용 생략};
}

-> 인터페이스의 구현

 

 

추상 클래스와 인터페이스의 공통점 : 추상 메서드를 가지고 있다.(미완성 설계도)

 

추상 클래스와 인터페이스의 차이점: 인터페이스는 iv를 가질 수 없다. 

 

인터페이스 타입 매개변수는 인터페이스 구현한 클래스의 객체(인스턴스)만 가능하다.  

인터페이스를 메서드의 리턴타입으로 지정할 수 있다. 인터페이스를 구현한 클래스의 인스턴스를 반환한다. 

 

Fightable method() {
	...
    Fighter f = new Fighter();
    return f; // 인터페이스를 구현한 객체를 반환, (Fghter이지만 조상 타입의 Fightable로 형변환 가능)

} // 두 문장을 return new Fighter();로 한 문장으로 바꿀 수 있다.

class Fighter extends Unit implements Fightable {
	public void move(int x, int y) {내용 생략}
    public void attack(Fightable f) {내용 생략}
}

위에 있는 코드에서는 'Fightable f = method();'와 'Fightable f = new Figher();'이 같은 의미로 사용된다. 

 

리턴 타입이 인터페이스라는 것은 메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환한다는 것을 의미한다. 

interface Parseable {
	//구문 분석작업을 수행
    public abstract void parse(String filename)'
}

class ParserManager {
	//리턴 타입이 Parseable 인터페이스이다. 
    public static Parseable getParser(String type){
   		 if (type.equals("XML")){
    		return new XMLParser();
    	 } else {
        	Parseable p = new HTMLParser();
            return p;
            // return new HTMLParser();
        }
    }
}

class XMLParser implements Parseable {
	public void parse(String fileName) {
    //* 구문 분석작업을 수행하는 코드를 적는다. */
    	System.out.println(fileName + "- XML parsing completed. ");
    }
}
class HTMLParser implements Parseable {
	public void parse(String fileName) {
    //* 구문 분석작업을 수행하는 코드를 적는다. */
    	System.out.println(fileName + "- HTML parsing completed. ");
    }
}

class ParserTest {
	public static void main(String args[]){
    	Parseable parser = ParserManger.getParser("XML");
        parser.parse("document.xml");
        parser = ParserManager.getParser("HTML");
        parser.parse("document2.html");
    }
}


/*
>>> 실행결과:
    document.xml - XML parsing completed.
    document2.html - HTML parsing completed.
*/

 

 

인터페이스의 장점1

- 두 객체 간의 '연결, 대화, 소통'을 돕는 '중간 역할'을 한다.

- 선언(설계)와 구현을 분리시킬 수 있게 한다. 

- 느슨한 결합으로 변경에 유연한 코드가 된다.

 

class A {
	public void method(B b) {
    	b.method();
    }
}

class B {
	public void method() {
    	System.out.println("B클래스의 메서드");
     }
}

class C {
	public void method() {
    	System.out.println("C클래스의 메서드");
     }
}

public class InterfaceTest {
	public static void main(String[] args){
    	A a = new A();
        a.method(new B()); // A가 B를 사용(의존)
    }
}

A가 C를 사용하기 위해서는

1. A클래스의 method 메소드의 매개변수를 C로 바꿔주어야 한다. 

2. main에서 a.method에 C 객체를 생성하고 입력해야 한다.

--> A의 변경을 없애기 위해서 인터페이스를 활용하면 된다. 

 

 

class A {
	public void method(I i) { // 인터페이스를 구현한 것들만 들어올 수 있다. 
    	i.method();
    }
}

// B클래스의 선언과 구현을 분리
interface I {
	public void method();
}

class B implements I {
	public void method() {
    	System.out.println("B클래스의 메서드");
     }
}

class C implements I {
	public void method() {
    	System.out.println("C클래스의 메서드");
     }
}

public class InterfaceTest {
	public static void main(String[] args){
    	A a = new A();
        a.method(new B()); // A가 B를 사용(의존)
        a.method(new C()); // A가 B를 사용(의존)
    }
}

--> 인터페이스를 활용하여 수정한 코드이다. 

코드의 변경이 적어진다.  

 

인터페이스의 장점2

- 개발 시간을 단축할 수 있다.

- 변경에 유리한 유연한 설계가 가능하다.

- 표준화가 가능하다.

- 서로 관계없는 클래스들을 관계를 맺어줄 수 있다.