[Java] 인터페이스 : 상속, 타입, 다형성

Local Gaji·2023년 8월 18일

이것이 자바다

목록 보기
10/18

🎈 인터페이스 상속

인터페이스도 상속이 가능하며, 다중 상속을 허용한다.

public interface Child extends ParentA, ParentB {
  ...
}

자식 인터페이스의 구현 클래스는 자식 인터페이스와 부모 인터페이스의 모든 추상 메서드 를 재정의해야 한다.

이 구현 클래스는 자식 인터페이스 변수나 부모 인터페이스 변수에 대입될 수 있다.

Child child = new 구현클래스();  // 모든 추상메서드 호출가능
ParentA pA = new 구현클래스();   // ParentA의 추상메서드 호출 가능
ParentB pB = new 구현클래스();   // ParentB의 추상메서드 호출 가능

🎈 타입 변환


🔰 자동 타입 변환

인터페이스 변수에 구현 클래스를 집어넣으면서 자동 타입 변환이 발생한다.

인터페이스명 변수 = new 구현클래스();

만약 구현 클래스의 자식 클래스가 있다면, 이 자식 클래스도 인터페이스 변수에 대입시켜 인터페이스 타입으로 자동 변환할 수 있다.

/* InterfaceA.java */
public interface InterfaceA { ... }

/* 구현클래스.java */
public class 구현클래스 implements interfaceA { ... }

/* Child.java */
public class Child extends 구현클래스 { ... }

/* 사용 */
InterfaceA interA;
interA = new 구현클래스();
interA = new Child();

🔰 강제 타입 변환

인터페이스 타입을 구현 클래스 타입으로 강제 변환한다.

구현클래스 변수 = (구현클래스) 인터페이스변수;

구현 클래스를 인터페이스 변수에 대입해서 자동 변환 되었을때, 인터페이스에 선언되지 않은 메서드는 사용할 수가 없다. 이 메서드들을 사용하고 싶다면, 구현 클래스의 타입을 다시 구현클래스타입 으로 강제 변환해야 한다.

/* InterA.java */
public interface interA { 
  void methodA();
}

/* ImpleA.java */
public class ImpleA implements interA {
  @Override
  public void methodA() { ... }
  
  public void methodB() { ... }   // 추가 메서드
}

/* 자동 타입 변환 : methodA 호출 가능 */
InterA intera = new ImpleA();
intera.methodA();

/* 강제 타입 변환 : methodA, methodB 호출 가능 */
ImpleA implea = (ImpleA) intera;
implea.methodB();

🎈 인터페이스 다형성

인터페이스의 구현클래스A와 구현클래스B가 있을 때, 어떤 구현 클래스가 인터페이스 변수에 대입되었는지에 따라서 실행 코드의 결과가 달라질 수 있다.

/* Inter.java */
public interface Inter {
  void method();   // 추상 메서드
}

/* ImpleA.java */
public class ImpleA implements Inter {
  public method() {
    System.out.println("A")  
  }
}

/* ImpleB.java */
public class ImpleB implements Inter {
  public method() {
    System.out.println("B")  
  }
}

/* 사용 */
Inter inter = new ImpleA();
inter.method();    // A 출력

Inter inter = new ImpleB();
inter.method();    // B 출력

🔰 매개변수 다형성

매개변수 타입을 인터페이스로 선언하면, 메서드 호출 시 구현 클래스를 대입할 수 있다.

public class 클래스 {
  void method(인터페이스타입 인터페이스변수) { ... }
}

인터페이스 CPU 와 구현 클래스 Intel, AMD 가 있고, 추상 메서드 powerOn 를 각각 재정의한다.

/* CPU.java */
public interface CPU {
  void powerOn();
}

/* Intel.java */
public class Intel implements CPU {
  @Override
  public void powerOn() { ... }
}

/* AMD.java */
public class AMD implements CPU {
  @Override
  public void powerOn() { ... }
}

외부 클래스인 Desktopstart 메서드에서 powerOn 를 호출하는데, 이때 CPU 타입 매개변수를 이용해서 호출한다.

/* Desktop.java */
public class Desktop {
  void start(CPU cpu) { 
    cpu.powerOn();
  }
}


/* 실행 */
Desktop pc1 = new Desktop();
Intel intel = new Intel();
AMD amd = new AMD();

pc1.start(intel);  
pc1.start(amd);
  1. start 메서드의 매개변수 타입이 CPU 로 정해져있지만, 구현 클래스인 Intel , AMD 타입이 들어가서 자동 타입 변환이 발생한다.
  2. start 메서드가 실행될 때, powerOn() 메서드는 각 구현 클래스에서 Override 된 버전으로 실행된다.
  3. start 메서드에 매개변수로 어떤 구현 클래스가 들어가냐에 따라 실행 결과가 달라진다.

🔰 타입 확인

start 메서드에서 받은 구현 클래스가 인터페이스 타입으로 자동 타입 변환 되었는데, 이 구현 클래스의 원래 타입을 확인하고 싶다면 instanceof 연산자를 사용한다.

public void start(CPU cpu) {
  if(cpu instanceof Intel) {
    Intel intel = (Intel) cpu;   
    // intel 변수 사용
  }
}

구현 클래스가 Intel 타입일 경우, CPU 타입으로 자동 변환된 Intel 구현 클래스를 다시 Intel 타입으로 강제 변환 시켜준다.

위 코드는 아래와 같이 우측타입변수 를 이용해서 표현할 수도 있다.

public void start(CPU cpu) {
  if(cpu instanceof Intel intel) {
    // intel 변수 사용  
  }
}

클래스 상속 타입 확인과 유사함


0개의 댓글