라봉이의 개발 블로그

java의 정석 7강. 객체지향프로그래밍2(하) 본문

Java/Java의 정석 읽고 정리

java의 정석 7강. 객체지향프로그래밍2(하)

Labhong 2018. 6. 3. 16:04
반응형

객체지향은 c++과 유사한 점이 많으니 특징과 다른 점만 짚고 넘어가도록 하겠다.



7. 인터페이스

7.1 인터페이스란?


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

추상클래스를 '미완성 설계도'라고 한다면 인터페이스는 밑그림만 그려져 있는 '기본 설계도'라고 할 수 있다.



7.2 인터페이스의 작성


인터페이스를 작성하는 것은 클래스와 같지만, 다만 키워드로 class 대신 interface를 사용하는 것만 다르다.

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

일반적인 클래스와 달리 인터페이스의 멤버들은 다음과 같은 제약사항이 존재한다.


  • 모든 멤버변수는 public static final이어야 하며, 이를 생략할 수 있다.

  • 모든 메서드는 puiblic abstract여야 하며, 이를 생략할 수 있다.



7.3 인터페이스의 상속

인터페이스는 인터페이스로부터만 상속받을 수 있으며, 클래스와는 달리 다중상속이 가능하다.
interface Movable {
  // 위치 x,y로 이동하는 기능
  puiblic abstract void move(x, y);
}
interface Attackable {
  // 지정된 대상을 공격하는 기능
  void attack(Unit u);          // puiblic abstract 생략가능
}

interface Fightable extends Movable, Attackable { }


7.4 인터페이스의 구현

인터페이스는 자신에 정의된 추상메서드의 몸통을 만들어주는 클래스를 만들어야 구현이 가능하다.
대신 extends 대신 키워드 implements를 사용한다.
class Fighter implements Fightable {
  public void move(int x, int y); { ... }
  public void attack(Unit u) { ... }
}

만일 구현하는 인터페이스의 메서드 중 일부만 구현했다면 class 앞에 abstract 키워드를 붙여야 한다(추상클래여야만 한다).

다음과 같이 상속 구현을 동시에 할 수도 있다.
class Fighter extends Unit implements Fightable {
  public void move(int x, int y); { ... }
  public void attack(Unit u) { ... }
}


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

만일 두 개의 클래스로부터 상속을 받아야 할 상황이라면, 두 조상클래스 중에서 비중이 높은 쪽을 선택해 상속 받고 다른 한 쪽은 클래스 내부의 멤버로 포함시키는 방식으로 처리하거나 어느 한 쪽의 필요한 부분을 뽑아서 인터페이스로 만든 다음 구현하도록 한다.
class Tv {
    protected boolean power;
    protected int channel;
    protected int volume;

    public void power() { power = !power; }
    public void channelUp() { channel++; }
    public void channelDown() { channel--; }
    public void volumeUp() { volume++; }
    public void volumeDown() { volume--; }
}

class VCR {
    protected int counter;

    public void play() {

    }
    public void stop() {

    }
    public void reset() {
        counter = 0;
    }
    public int getCounter() {
        return counter;
    }
    public void setCounter(int counter) {
        this.counter = counter;
    }
}


두 클래스를 상속하는 클래스를 만들고 싶지만 다중상속은 불가능하므로 한 쪽만 선택해 다른 한 쪽의 메서드와 일치하는 새로운 인터페이스를 만든다.

따라서 VCR 클래스에 정의된 메서드와 일치하는 추상메서드를 갖는 인터페이스를 정의한다.

public interface IVCR {
  public void play();
  public void stop();
  public void reset();
  public int getCounter();
  public void setCounter(int counter);
}


이제 IVCR을 구현하고 Tv클래스를 상속받는 TVCR 클래스를 작성한다.

public class TVCR extends Tv implements IVCR {
  VCR vcr = new VCR();

  public void play() {
    vcr.play();
  }
  public void stop() {
    vcr.stop();
  }
  public void reset() {
    vcr.reset();
  }
  public int getCounter() {
      return vcr.getCounter();
  }
  public void setCounter(int counter) {
      vcr.setCounter(counter);
  }
}


이런 식으로 다형적 특성을 살리면서 다중상속을 대체할 수 있다.



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


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


  • Fighter 클래스가 Fightable 인터페이스 상속받았을 때

Fightable f = new Fighter();
  • 메서드의 매개변수 타입으로 사용될 때

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

등등이 있다.



7.7 인터페이스의 장점


인터페이스를 이해하기 전에 다음 두 가지 사항을 염두해 두고 있어야 한다.


  • 클래스를 사용하는 쪽클래스를 제공하는 쪽이 있다.

  • 메서드를 사용하는 쪽에서는 사용하려는 메서드의 선언부만 알면 된다.


예를 들어서 클래스 A와 B가 있다고 가정하자.

클래스 A는 클래스 B의 인스턴스를 생성하고 메서드를 호출한다.



이 경우 클래스 A를 작성하기 위해 클래스 B가 이미 작성되어야 한다. 그리고 B에 변경점이 생기면 클래스 A도 변경되어야 한다.

이와 같이 직접적인 관계는 한 쪽이 변경되면 다른 한 쪽도 변경되어야 한다는 단점이 있다.


하지만 인터페이스를 매개체로 해서 클래스 A가 인터페이스를 통해서 클래스 b의 메서드에 접근하도록 하면, 클래스 B에 변경사항이 생기거나 클래스 B와 같은 기능의 다른 클래스로 대체되어도 클래스 A는 전혀 형향을 받지 않도록 하는 것이 가능하다.



반응형
Comments