📝 객체 형변환
- 기본형 변수처럼 참조변수도 형변환(Casting)이 가능하다.
- 단, 서로 상속 관계에 있는 클래스 사이에서만 가능하다.
Parent parent = new Child();
즉 오버라이드된 기능만 사용가능하고, 추가적으로 구현한 기능은 사용할 수 없다.
// 👉 가능하다.
A a1 = new B();
A a2 = new X();
-------------------
A a3 = new C();
A a4 = new Y();
-------------------
B b1 = new C();
X x1 = new Y();
-------------------
C c = new C();
B b2 = c;
-------------------
Y y = new Y();
X x2 = y;
// ❗❗ 불가능하다.
C c1 = new B();
C c2 = new X();
✍ 암묵적 형변환 코드 예시 )
// 부모 클래스
public class Unit {
private String name;
// 생성자 정의
public Unit(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 재정의 대상
public void attack() {
System.out.println(this.name + " >>> 공격준비 ");
}
}
// 자식 클래스
// 육군
public class Army extends Unit {
// 부모 클래스의 생성자를 강제 호출하기 위한 생성자
public Army(String name) {
super(name);
}
// 공격의 형태를 육군에 맞게 변경하지만,
// 부모 클래스가 가지고 있는 공격 준비 기능을
// super 키워드를 통해 보전
@Override
public void attack() {
super.attack();
System.out.println(super.getName() + " >> 지상공격 실행");
}
public void tank() {
System.out.println(super.getName() + " >> 탱크공격");
}
}
// 해군
public class Navy extends Unit{
public Navy(String name) {
super(name);
}
@Override
public void attack() {
super.attack();
System.out.println(this.getName() + " >> 어뢰발사");
System.out.println(this.getName() + " >> 지상 상륙");
}
public void nucleus() {
System.out.println(this.getName() + " >> 핵미사일");
}
}
// 공군
public class AirForce extends Unit {
public AirForce(String name) {
super(name);
}
@Override
public void attack() {
super.attack();
System.out.println(super.getName() + " >> 이륙");
System.out.println(super.getName() + " >> 공중공격 실행");
}
public void bombing() {
System.out.println(this.getName() + " >> 폭격");
}
}
// Main 클래스
public class Main01 {
public static void main(String[] args) {
// army, navy, airforce로 각각의 객체생성
Army army = new Army("육군");
Navy navy = new Navy("해군");
AirForce air = new AirForce("공군");
// 그 각각의 객체의 고유 기능을 사용
army.tank();
navy.nucleus();
air.bombing();
System.out.println("----------------------------------");
// 상위 객체 형태로 암묵적 형변환
Unit temp1 = army;
Unit temp2 = navy;
Unit temp3 = air;
// 형변환이 되더라도 상속받거나 재정의한(Override)
// 자신들의 기본 특성들은 그대로 유지
temp1.attack();
System.out.println();
temp2.attack();
System.out.println();
temp3.attack();
// 상위 클래스 형태로 형변환이 되면, 자신들의 독립 기능은
// 사용하지 못한다.
// temp1.tank();
// temp2.nucleus();
// temp3.bombing();
}
}
👉 실행 결과
육군 >> 탱크공격
해군 >> 핵미사일
공군 >> 폭격
----------------------------------
육군 >>> 공격준비
육군 >> 지상공격 실행
해군 >>> 공격준비
해군 >> 어뢰발사
해군 >> 지상 상륙
공군 >>> 공격준비
공군 >> 이륙
공군 >> 공중공격 실행
객체가 상위클래스의 형태로 형변환 되더라도 Override된 자신의 기능은 잃지 않는다.
하지만, 추가적으로 구현한 기능은 사용할 수 없다.
ChildClass child = (ChildClass)parent;
❗❗ 객체가 최초로 생성될 때 자식 클래스 형태로 생성되고, 부모 형태로 암묵적 형변환이 된 상태를
다시 원래의 자식 클래스 형태로 되돌릴 경우에만 가능해진다.
ChildClass child1 = new ChildClass();
ParentClass parent = child1; // 암묵적 형변환
ChildClass child2 = (ChildClass)parent; // 명시적 형변환
✍ 명시적 형변환 코드 예시 )
public class Main01 {
public static void main(String[] args) {
// army, navy, airforce로 각각의 객체생성
Army army = new Army("육군");
Navy navy = new Navy("해군");
AirForce air = new AirForce("공군");
System.out.println("----------------------------------");
// 상위 객체 형태로 암묵적 형변환
Unit temp1 = army;
Unit temp2 = navy;
Unit temp3 = air;
temp1.attack();
System.out.println();
temp2.attack();
System.out.println();
temp3.attack();
System.out.println("----------------------------------");
// 하위 클래스 형태로 명시적 형변환
Army re1 = (Army)temp1;
Navy re2 = (Navy)temp2;
AirForce re3 = (AirForce)temp3;
re1.tank();
re2.nucleus();
re3.bombing();
}
}
👉 실행 결과
육군 >>> 공격준비
육군 >> 지상공격 실행
해군 >>> 공격준비
해군 >> 어뢰발사
해군 >> 지상 상륙
공군 >>> 공격준비
공군 >> 이륙
공군 >> 공중공격 실행
----------------------------------
육군 >> 탱크공격
해군 >> 핵미사일
공군 >> 폭격
✍ 명시적 형변환이 불가능한 경우
Unit u = new Unit();
Army army = (Army)u; // 최초 객체 생성이 부모 형태로 만들어진 경우 불가능하다.
Army army = new Army();
Unit u = army;
Navy navy = (Navy)u; // 다른클래스로 만들어진 객체에 명시적 형변환은 불가능하다.
하위 클래스 형태로 명시적 형변환을 함으로써, 자신들의 독립 기능(메서드)들을 사용할 수 있다.