본문으로 바로가기

Java- 인터페이스

category 프로그래밍 언어/Java 2019. 7. 11. 17:42

1. 인터페이스

추상클래스의 일종으로 추상의 정도가 높습니다.

 

추상 클래스는 미완성의 의미를 갖는다면 인터페이스는 밑그림이라 할 수 있습니다.

 


2. 인터페이스 방법

interface InterfaceName {

  public static final 타입 명 = 값;
  public abstract 메소드명();

}
  • 멤버변수: public static final이 붙어야 한다.
  • 메소드: public abstract 이며 이를 생략 가능하다.
  • jdk 1.8부터 static, default 메서드는 예외이다.

인터페이스는 인터페이스로부터 상속이 가능합니다.

interface A {
  void a(int x, int y);
}

interface B {
  void b(int u);
}

// 인터페이스만 상속가능, 다중상속
interface C extends A, B {
  // ...
}

3. 인터페이스 구현

클래스에서 인터페이스를 구현하려면 implements를 사용합니다.

class ClassName implements InterfaceName {
  // 인터페이스에 정의된 추상메서드 구현
}

이는 인스턴스 생성이 불가능하며 인터페이스의 일부 메서드를 구현하고자 한다면 나머지 메서드는 abstract가 붙어야합니다.

 

상속, 구현 모두 가능합니다.

// 테스트 클래스
public class FighterTest {
  public static void main(String[] args) {

    Fighter fighter = new Fighter();

    if (fighter instanceof Unit)
      System.out.println("fighter는 Unit클래스의 자손입니다.");
    if (fighter instanceof Fightable)
      System.out.println("fighter는 Fighter인터페이스를 구현했습니다.");
    if (fighter instanceof Moveable)
      System.out.println("fighter는 Moveable인터페이스를 구현했습니다.");
    if (fighter instanceof Attackable)
      System.out.println("fighter는 Attackable인터페이스를 구현했습니다.");
    if (fighter instanceof Object)
      System.out.println("fighter는 Object클래스의 자손입니다.");

  }
}

// 파이터 클래스 : 유닛 클래스 상속, 싸움 인터페이스 구현
class Fighter extends Unit implements Fightable {

  public void move(int x, int y) {
    // ...
  }

  public void attack(Unit unit) {
    // ...
  }
}

// 유닛 클래스
class Unit {
  int currentHP;
  int x;
  int y;
}

// 싸움 인터페이스 : 이동, 공격 인터페이스 다중상속
interface Fightable extends Moveable, Attackable {

}

// 이동 인터페이스
interface Moveable {
  void move(int x, int y);
}

// 공격 인터페이스
interface Attackable {
  void attack(Unit unit);
}
결과
fighter는 Unit클래스의 자손입니다.
fighter는 Fighter인터페이스를 구현했습니다.
fighter는 Moveable인터페이스를 구현했습니다.
fighter는 Attackable인터페이스를 구현했습니다.
fighter는 Object클래스의 자손입니다.

즉 Fightable은 인터페이스 Moveable과 Attackable를 상속하고 

 

이는 클래스 Fighter가 Fightable 인터페이스를 구현하고 Unit클래스를 상속합니다.


4. 인터페이스 장점

  • 개발 시간 단축
  • 표준화 가능
  • 서로 관계없는 클래스의 관계를 맺음
  • 독립 프로그래밍 가능

5. 인터페이스 고려사항

  • 클래스 사용(Client)와 클래스 제공(Server)가 있다.
  • Client입장에서는 Server의 메서드 선언부 만 알면 된다.

5.1)우선 인터페이스를 사용하지 않은 직접적인 관계를 살펴봅시다.

 

// 인터페이스 테스트 클래스
public class InterfaceTest {
  public static void main(String[] args) {
    A a = new A();
    a.methodA(new B());
  }
}

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

class B {
  public void methodB() {
    System.out.println("methodB()");
  }
}
methodB()

즉 A클래스 B클래스를 만들고 메인에서 직접적인 관계를 통해 A 인스턴스 생성 후 A의 methodA로 인자는 B클래스 인스턴스를 넘겨줍니다. 

 

여기서는 A클래스를 사용하려면 B클래스가 작성되어 있어야합니다. B의 메서드가 변경 시 A의 메서드도 변경되어야 합니다. 

 

서로 직접적으로 관계가 있기 때문에 의존 관계로 서로 영향을 미치게 됩니다.

 

 

5.2) 인터페이스를 사용한 간접적인 관계를 살펴봅시다.

 

public class InterfaceTest2 {
  public static void main(String[] args) {
    A a = new A();
    a.autoPlay(new B());
    a.autoPlay(new C());
  }
}

class A {
  void autoPlay(I i) {
    i.play();
  }
}

interface I {
  public abstract void play();
}

class B implements I {
  public void play() {
    System.out.println("play in B class");
  }
}

class C implements I {
  public void play() {
    System.out.println("play in C class");
  }
}
play in B class
play in C class

여기서는 B클래스와 C클래스가 I인터페이스를 구현하였고 클래스 A는 메서드의 매개변수로 인터페이스를 넣었습니다.

 

즉 B와 C는 인터페이스를 구현하였기에 main에서 클래스 A의 매개변수로 적용이 될 수 있습니다.

 

즉 A는 B와 C를 직접 호출 하는 것이 아닌 인터페이스를 통해서 호출하였습니다.(간접적)

 

이에 따라서 A는 B의 영향을 받지 않고 위에서 말한 장점중 하나인 독립적인 프로그래밍이 가능하다는 뜻입니다.

 

즉 선언부만 알면 되는것이죠

 

5.3) 제 3 클래스

 

public class InterfaceTest3 {
  public static void main(String[] args) {
    A a = new A();
    a.methodA();
  }
}

class A {
  void methodA() {
    I i = InstanceManager.getInstance();
    i.methodB();
    // Object에 정의된 메서드들은 모두 호출가능
    System.out.println(i.toString());
  }
}

interface I {
  public abstract void methodB();
}

class B implements I {
  public void methodB() {
    System.out.println("methodB in B class");
  }

  public String toString() {
    return "class B";
  }
}

class InstanceManager {
  // 인스턴스를 제공한다.
  public static I getInstance() {
    // 인스턴스를 변경해야될 경우 이부분만 변경
    return new B();
  }
}

클래스 B가 인터페이스 I를 구현하고 인스턴스관리자라는 클래스가 이를 리턴해주는 getInstance() 메소드가 있습니다.

 

이에 따라 클래스 A는 인스턴스관리자에 의해 getInstance를 호출하여 인터페이스를 구현한 B를 받습니다.

 

메인에서 직접적인 인스턴스 생성 없이 인스턴스관리자에 의해서 제공받습니다.

 

다른 클래스 인스턴스가 변경 될 경우 인스턴스 관리자의 getInstance() 메소드만 수정하면 됩니다.

 

'프로그래밍 언어 > Java' 카테고리의 다른 글

Java - 컬렉션 프레임워크  (0) 2019.07.15
Java- 예외  (0) 2019.07.12
Java- 추상클래스  (0) 2019.07.10
Java - 다형성  (0) 2019.07.10
Java - 제어자  (0) 2019.07.10