[기본 개념] 2 | (7.2) 인터페이스 다형성, 장점

728x90

[기본 개념] 2 | (7.2) 인터페이스 다형성, 장점

1 인터페이스란?

2 인터페이스의 작성

3 인터페이스의 상속

4 인터페이스의 구현

5 인터페이스를 이용한 다중상속

6> 인터페이스를 이용한 다형성

7> 인터페이스의 장점

8 인터페이스의 이해

9 디폴트 메서드

6. 인터페이스를 이용한 다형성

 인터페이스도 인터페이스 타입의 참조변수로 이를 구현한 클래스의 인스턴스를 참조할 수 있으며, 인터페이스 타입으로 형변환도 가능하다.

 

 인터페이스 Fightable을 클래스 Fighter가 구현했을 때, 다음과 같이 FIghter인스턴스를 Fightable타입의 참조변수로 참조하는 것이 가능하다.

 

Fightable f = (Fightable)new Fighter( ) ;

또는

Fightable f = new Fighter( ) ;

 

 따라서 인터페이스는 매개변수의 타입으로 사용될 수 있다. 그리고 다음과 같이 메서드의 리턴타입으로 인터페이스의 타입을 지정하는 것 역시 가능하다.

 

        Fightable method( ) {

            · · · 

            Fighter f = new Fighter( ) ;

            return f ;

        }

 

 리턴타입이 인터페이스라는 것은

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

 

예제/ParserTest.java

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

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.");
    }
}
실행결과

document.xml- XML parsing completed.
document2.html- HTML parsing completed.

 

 ParserManager클래스의 getParser메서드는 매개변수로 넘겨받는 type의 값에 따라 XMLParser인스턴스 또는 HTMLParser인스턴스를 반환한다.

7. 인터페이스의 장점

인터페이스의 장점을 정리하면 다음과 같다.

 

1. 개발시간을 단축시킬 수 있다.

- 인터페이스가 작성되면, 이를 사용해서 구현하는 클래스가 작성되기 전에 동시에 개발을 진행할 수 있다.

 

2. 표준화가 가능하다.

- 프로젝트에 사용되는 기본 틀을 인터페이스로 작성하면 일관되고 정형화된 프로그램의 개발이 가능하다.

 

3. 서로 관계없는 클래스들에게 관계를 맺어 줄 수 있다.

- 서로 상속관계도 아니고 같은 조상클래스도 아닌 클래스들에게 하나의 인터페이스를 공통적으로 구현하도록 함으로써 관계를 맺어 줄 수 있다.

 

4. 독립적인 프로그래밍이 가능하다.

- 인터페이스를 이용하면 선언과 구현을 분리시킬 수 있기 때문에 한 클래스의 변경이 관련된 다른 클래스에 영향을 미치지 않는 독립적인 프로그래밍이 가능하다.

 

 게임에 나오는 유닛을 클래스로 표현해봤다. 게임에 나오는 모든 유닛들의 최고조상은 Unit클래스이고 유닛의 종류는 지상유닛(GroundUnit)과 공중유닛(AirUnit)으로 나눠진다. 그리고 지상유닛에는 Marine, SCV, Tank가 있고, 공중유닛으로는 Dropship이 있다.

 

 SCV에게 Tank와 Dropship같은 기계화 유닛을 수리할 수 있는 기능을 제공하기 위해 repair메서드를 정의한다면 다음과 같을 것이다.

 

        void repair(Tank t) {

            // Tank를 수리한다.

        }

 

        void repari(Dropship d) {

            // Dropship을 수리한다.

        }

 

 이런 식으로 수리가 가능한 유닛의 개수만큼 오버로딩을 해야 할 것이다. 이것을 피하기 위해 공통조상으로 하면 좋겠지만 상속관계에서 이들의 공통점은 없다. 이때 인터페이스를 이용하면 이들 기계화 유닛에 공통점을 부여할 수 있다.

 

 다음과 같이 Repairable이라는 인터페이스를 정의하고 수리가 가능한 기계화 유닛에게 인터페이스를 구현하도록 하면 된다.

 

        interface Repairable { }

        class SCV extends GroundUnit implements Repairable {

            //  · · ·

        }

 

        class Tank extends GroundUnit implements Repairable {

            //  · · ·

        }

 

        class Dropship extends AirUnit implements Repairable {

            //  · · ·

        }

 

 그리고 repair메서드의 매개변수의 타입을 Repairable로 선언하면, 이 메서드의 매개변수로 Repairable인터페이스를 구현한 클래스의 인스턴스만 받아들여질 것이다.

 

        void repair(Repairable r) {

            // 매개변수로 넘겨받은 유닛을 수리한다.

        }

 

 

 

 

 

출처 | Java의 정석 (남궁 성)

728x90