인터페이스 변수 = 구현객체;
는 자동으로 타입변환이 일어난다.
public class Main {
public static void main(String[] args) {
A a1 = new B(); // A 인터페이스에 구현체 B 대입 -> 타입 A로 자동 타입변환
A a2 = new C(); // A 인터페이스에 구편체 B를 상속받은 C 대입 -> 타입 A로 자동 타입변환
}
}
interface A { }
class B implements A {}
class C extends B {}
구현객체타입 변수 = (구현객체타입) 인터페이스 변수;
는 (구현객체타입)
으로 강제 타입변환이 된다.
public class Main {
public static void main(String[] args) {
A a1 = new B(); // A 인터페이스에 구현체 B 대입
a1.a();
a1.b(); // ERROR -> a1은 인터페이스 A 타입이기 때문에
// a() 메서드만 가지고 있다.
----- 강제 타입 변환 -----
B b = (B) a1;
b.a();
b.b(); // 강제 타입 변환
System.out.println();
----- 자동 타입 변환 -----
A a2 = new C(); // A 인터페이스에 구편체 B를 상속받은 C 대입
a2.a();
a2.b(); // ERROR -> 타입이 C 라면 모두 가능하지만,
a2.c(); // ERROR A 타입으로 자동형변환되어 불가능하다.
----- 강제 타입 변환 -----
C c = (C) a2;
c.a();
c.b(); // 강제 타입 변환
c.c(); // 강제 타입 변환
}
}
interface A {
void a();
}
class B implements A {
@Override
public void a() {
(...)
}
public void b() {
(...)
}
}
class C extends B {
public void c() {
(...)
}
}
자동형변환으로 인해 쓰지 못한 메서드르 사용하고 싶으면 강제형변환을 통해 사용한다.
👉 상속에서의 형변환과 유사하다.
예시) 이해하기 쉽게 TV 리모컨 !
1. 시골TV를 리모컨으로 조정한다.
2. 시골TV를 소녀TV로 교체한 후 시골TV의 모든 상태가 유지되어야한다.
3. 소녀TV로 모든 상태가 넘어가고 정상적으로 작동되어야한다.
public abstract class Tv {
private String company;
private int channel = 1;
(...)
public Tv(String company) {
this.company = company;
}
public void displayChannel(int channel) {
System.out.println("현재 채널은 " + channel);
}
public String getCompany() {
return company;
}
public int getChannel() {
return channel;
}
public void setChannel(int channel) {
this.channel = Math.max(channel, 0);
}
(...)
}
public class CountryTv extends Tv implements MultiRemoteController{
public countryTv(String company) {
super(company);
}
@Override
public void channelUp() {
setChannel(getChannel() + 1);
displayChannel(getChannel());
}
@Override
public void channelDown() {
setChannel(getChannel() - 1);
displayChannel(getChannel());
}
}
public class GirlTv extends Tv implements MultiRemoteController{
public girlTv(String company) {
super(company);
}
@Override
public void channelUp() {
setChannel(getChannel() + 1);
displayChannel(getChannel());
}
@Override
public void channelDown() {
setChannel(getChannel() - 1);
displayChannel(getChannel());
}
}
자식 클래스의 메서드들을 보면 결국 호출하는 건 부모 클래스에 속한 메서드이다. 그러므로 TV가 바뀌어도 상태를 유지할 수 있다.
public interface MultiRemoteController {
void channelUp();
void channelDown()
}
public class Main {
public static void main(String[] args) {
MultiRemoteController mrc = new CountryTv("Country"); // 자동 형 변환
// CountryTv mrc = new CountryTv("Country");
mrc.channelDown(); // default : channel = 1
mrc.channelUp();
--------- 소녀TV로 교체 ---------
mrc = new GirlTv("Girl");
mrc.channelUp();
}
}
MultiRemoteController mrc = new countryTv("Country");
에서 MultiRemoteController
대신 CountryTv
라고 해도 정상적으로 실행이 된다.
Q. 그럼 왜 굳이 인터페이스를 사용할까 ?
A.
mrc = new GirlTv("Girl");
에서 오류가 발생한다.MultiRemoteController
가 아니라CountryTv
이면mrc
를GirlTv
로 바꿀 수 없다.
공용으로 기능을 돌아가게 하기 위해서 인터페이스를 사용한다.