* JAVA - 인터페이스(1)

jodbsgh·2022년 3월 27일
0

💡"JAVA"

목록 보기
26/67

인터페이스란?

인터페이스는 추상클래스처럼 추상메서드를 갖지만 추상클래스보다 추상화 정도가 높아서 몸통을 갖춘 일반 메서드 또는 멤버변수를 구성원으로 가질 수 없다.

추상메서드와 상수만을 멤버로 가질 수 있으며, 그 외의 다른 어떠한 요소도 허용하지 않는다.

인터페이스의 작성

interface 인터페이스이름{
	public static final 타입 상수 이름 = 값;
    public abstract 메서드이름(매개변수목록);
}
  • 모든 멤버변수는 public static final 이어야 하며, 이를 생략할 수 있다.
  • 모든 메서드는 public abstract 이어야 하며, 이를 생략할 수 있다.
    단, static 매서드와 디폴트 메서드는 예외

인터페이스의 상속

인터페이스는 인터페이스로부터만 상속받을 수 있으며, 클래스와는 달리 다중상속, 즉 여러 개의 인터페이스로부터 상속을 받는 것이 가능하다.

interface Movable{
	/** 지정딘 위치 (x,y)로 이동하는 기능의 메서드 */
    void move(int x, int y);
}
interface Attackable {
	/** 지정된 대상을 공격하는 기능의 메서드 */
    void attack(Unit u);
}

interface Fightable extends Movable, Attackable {  }

자손 인터페이스는 조상 인터페이스에 정의된 멤버를 모두 상속받는다.

인터페이스의 구현

인터페이스가 상속받는 방법은 'implements'를 사용할 뿐이다.

class 클래스이름 implements 인터페이스이름{
	//인터페이스에 정의된 추상메서드를 구현해야 한다.
}

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

만일 구현하는 인터페이스의 메서드 중 일부만 구현한다면, abstract를 붙여서 추상클래스로 선언해야 한다.

abstract class Fightable implements Fightable{	//추상클래스 일부 구현
	public void move (int x, int y) {/* 내용 생략*/}
}

다음과 같이 상속과 구현을 동시에 할 수도 있다.

	class Fighter extends Unit implements Fightable{
    	public void move(int x, int y){	/* 내용 생략 */}
        pyblic void attack(Unit u ) {/*내용 생략 */}
    }
예제)

class FighterTest{
	public static void main(String[] args)
    {
    	Fighter f = new Fighter();
        
        if(f instanceof Unit)
        	System.out.println("f는 Unit 클래스의 자손입니다.");
            
        if(f instanceof Fightable)
            System.out.println("f는 Fightable 인터페이스를 구현했습니다.");
            
        if(f instanceof Movable)
            System.out.println("f는 Movable 인터페이스를 구현했습니다.");
            
        if(f instanceof Attackable)
        	System.out.println("f는 Attackable 인터페이스를 구현했습니다.");
            
        if(f instanceof Object)
        	System.out.println("f는 Object 클래스의 자손입니다.");
        
    }	//main
}

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

class Unit{
	int currentHP //유닛의 체력
    int x;		  //유닛의 위치(x좌표)
    int y;		  //유닛의 위치(y좌표)
}
interface Fightable extends Movable, Attackable { }
interface Movable { void move (int x, int y); }
interface Attackable { void attack (Unit u); }

실행결과
f는 Unit클래스의 자손입니다.
f는 Fightable인터페이스를 구현했습니다.
f는 Movable인터페이스를 구현했습니다.
f는 Attackable인터페이스를 구현했습니다.
f는 Object클래스의 자손입니다.

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

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

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

	Fightable f = (Fightable) new Fighter();
    또는
    Fightable f = new Fighter();

인터페이스는 다음과 같이 메서드의 매개변수의 타입으로 사용될 수 있다.

void attack(Fightable f) {
	//...
}

인터페이스 타입의 매개변수가 갖는 의미
메서드 호출 시 해당 인터페이스를 구현한 클래스의 인스턴스를 매개변수로 제공해야한다는 것이다.
그래서 attack메서드를 호출할 때는 매개변수로 Fightable인터페이스를 구현한 클래스의 인스턴스를 넘겨주어야 한다.

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

위와 같이 Fightable 인터페이스를 구현한 Fighter클래스가 있을 때, attack메서드의 매개변수로 Fighter인스턴스를 넘겨줄 수 있다.

즉, attack(new Fighter())와 같이 할 수 있다는 것이다.

다음과 같이 메서드의 리턴타입으로 인터페이스의 타입을 지정하는 것 역시 가능하다.

	Fightable method() {
    	...
        Fighter f = new Fighter();		//이 두 문장을 바꿨을 시
        return f;						//return new Fighter(); 와 같다
    }

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

예제)

interface Parseable{
	// 구문 분석작업을 수행한다.
    public abstract void parse(String fileName);
}

class ParseManager{
	//리턴타입이 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 = ParserManager.getParser("XML");
        parser.parse("document.xml");
        parser = ParserManager.getParser("HTML");
        parser.parse("document2.html");
    }
}

실행결과

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

Parseable 인터페이스는 구문분석을 수행하는 기능을 구현할 목적으로 추상메서드 'parse(String fileName)'을 정의했다. 그리고 XMLParser 클래스와 HTMLParser클래스는 Parseable 인터페이스를 구현하였다.

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

	Parseable parser = ParseManger.getParser("XML");
    
    public static Parseable getParser(String type)
    {
    	if(type.equals("XML")){
        	return new XMLParser();
        } else {
        	Parseable p = new HTMLParser();
            return = p
        }
    }

만일 나중에 새로운 종류의 XML구문분석기 NewXMLPaser클래스가 나와도 ParserTest클래스는 변경할 필요 없이 ParserManager클래스의 getParser메서드에서 'return new XMLParser();' 대신 'return new NewXMLParser();'로 변경하기만 하면 된다.

이러한 장점은 특히 분산환경 프로그래밍에서 그 위력을 발휘한다. 사용자 컴퓨터에 설치된 프로그램을 변경하지 않고 서버측의 변경만으로도 사용자가 새로 개정된 프로그램을 사용하는 것이 가능하다.

profile
어제 보다는 내일을, 내일 보다는 오늘을 🚀

0개의 댓글