java/객체지향

[객체지향] 인터페이스

각시탈코더 2021. 7. 19. 15:50

● 인터페이스

 인터페이스는 일종의 추상클래스이다. 인터페이스는 추상클래스처럼 추상메서드를 갖지만, 추상글래스와 달리 몸통을 갖춘 일반 메서드 또는 멤버변수를 구성원으로 가질 수 없다. 즉, 추상메서드와 상수만을 멤버로 가질 수 있으며 그외 다른 요소는 허용하지 않는다. 인터페이스는 그 자체적으로 사용되기 보다는 다른 클래스를 작성하는데 도움 줄 목적으로 작성된다. 인터페이스는 키워드로 class 대신 interface를 사용한다. 그리고 접근제어자로 public 또는 default만 사용할 수 있다.

 

 

interface 인터페이스이름 {
     public static final 타입 상수이름= 값;
     public abstract 메서드이름(매개변수목록);
}

 

 

 인터페이스는 일반적인 클래스와 달리 다음과 같은 제약사항이 있다.

  1. 모든 멤버변수는 public static final 이어야 하며, 이를 생략할 수 있다.
  2. 모든 메서드는 public abstract 이어야 하며, 이를 생략할 수 있다. 

 

 

interface PlayingCard {
     public static final int SPADE = 4;
     final int DIAMOND = 3;  // public static final int DIAMOND = 3;
     static int HEART = 2;   // public static final int HEART = 2;
     int CLOVER = 1;         // public static final int CLOVER = 1;
     
     public abstarct String getCardNumber();
     String getCardKind();   // public abstract String getCardKind();
}

 

 

●인터페이스의 상속

 인터페이스는 인터페이스로부터만 상속받을 수 있다. 추상메서드는 충돌문제가 발생하지 않으므로 인터페이스는 클래스와 달리 다중상속을 받을 수 있다.

 

 

interface Movable {
      /** 지정된 위치(x, y)로 이동하는 기능의 메서드 **/
      void move(int x, int y);
}

interface Attackable {
      /** 지정된 대상(u)을 공격하는 기능의 메서드 **/
      void attack(Unit u);
}

interface fightable extends Movable, Attackable { }

 

 

 

 클래스의 상속과 마찬가지로 자손 인터페이스(Fightable)는 조상 인터페이스(Moveable, Attackable)에 정의된 멤버를 모두 상속받는다. 그래서 Fightable자체에는 정의된 멤버가 하나도 없지만 조상 인터페이스로부터 상속받은 두 개의 추상메서드, move(int x, int y)와 attack(Unit u)을 멤버로 갖게 된다.

 

 

●인터페이스의 구현

 인터페이스도 추상클래스처럼 그 자체로는 인스턴스를 생성할 수 없으며, 추상클래스가 상속을 통해 추상메서드를 완성하는 것처럼, 인터페이스도 자신에 정의된 추상메서드의 몸통을 만들어주는 클래스를 작성해야 하는데, 그 방법은 추상클래스가 자신을 상속받는 클래스를 정의하는 것과 다르지 않다. 다만 인터페이스를 구현한다는 의미로 키워드 'implements'를 사용한다.

 

 

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

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

 

 

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

 

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

 

 

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

 

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

 

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

 다형성을 학습할 때 자손클래스와 마찬가지로 인터페이스 타입의 참조변수로 클래스의 인터스턴스를 참조할 수 있으며, 인스턴스 타입으로의 형변환도 가능하다. 인터페이스 Fightable을 클래스 Fighter가 구현했을 때, Fighter인스턴스를 Fightable타입의 참조변수로 참조하는 것이 가능하다.

 

 

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

 

 

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

 

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

 

 

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

 

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

 

 위와 같이 Fightable 인터페이스를 구현한 Fighter클래스가 있을 때, attack메서드의 매개변수로 Fighter인스턴스를 넘겨 줄 수 있다. 즉, attack(new Fighter())와 같이 할 수 있다는 것이다. 그리고 아래처럼 메서드의 리턴타입으로 인터페이스를 지정하는 것도 가능하다.

 

 

Fightable method() {
      ...
     Fightable f = new Fightable();
     return f;
}

 

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

 

●인터페이스의 장점

 마지막으로 인터페이스를 사용하면 어떤 장점이 있는지 짧게 나열해보겠다.

  1. 개발시간을 단축시킬 수 있다.
  2. 표준화가 가능하다
  3. 서로 관계없는 클래스들에게 관계를 맺어 줄 수 있다.
  4. 독립적인 프로그래밍이 가능하다.

출처:자바의 정석 기초편(저자: 남궁성, 출판:도우출판)