[Java 자바] 7. 상속 ② 타입 변환과 다형성, instanceof
7-7. 타입 변환과 다형성
7-7-1 . 자동 타입 변환 (Promotion)
실행 도중에 자동적으로 타입 변환이 일어나는 것
- 자식은 부모의 특징과 기능을 상속 받기 때문에 부모와 동일하게 취급될 수 있음
- 아래 코드의 경우, Child클래스로 Child객체를 생성하고 이것을 Parent참조변수에 대입하면 자동 타입 변환이 일어남
- 바로 위의 부모가 아니더라도, 상속 계층에서 상위 타입이라면 자동 타입변환이 일어날 수 있음
Child c = new Child();
Parent p = c;
c == p // true
- 부모 타입으로 자동 타입 변환된 이후에는 부모 클래스에 선언된 필드와 메소드만 접근 가능
- 변수는 자식 객체를 참조하지만 변수로 접근 가능한 멤버는 부모 클래스 멤버로만 한정
- 단, 메소드가 자식클래스에서 오버라이딩 되었다면 자식 클래스가 대신 호출 (동적 바인딩)
//Parent.java
public class Parent {
public void method1() {
System.out.println("부모메소드1");
}
public void method2() {
System.out.println("부모메소드2");
}
}
//Child.java
public class Child extends Parent{
@Override
public void method2() {
System.out.println("자식메소드로 오버라이딩된 메소드2");
}
public void method3() {
System.out.println("자식 객체 고유 메소드3");
}
public static void main(String[] args) {
Child c = new Child();
Parent p = c;
c.method3();
p.method3(); // 접근 불가
c.method2(); //Child에서 오버라이딩된 메소드 출력
p.method2(); //Child에서 오버라이딩된 메소드 출력
}
}
7-7-2. 필드의 다형성
필드의 타입은 변함이 없지만, 실행 도중 어떤 객체를 필드로 저장하느냐에 따라 실행 결과가 달라질 수 있음
- 필드의 타입을 부모 타입으로 선언하면 다양한 자식 객체들이 저장될 수 있기 때문에 필요에 따라 자식 객체들을 교체하여 사용 가능
7-7-3. 하나의 배열로 객체 관리
객체를 배열로 관리하여 사용 가능
Class Car {
Tire frontLeftTire = new Tire("앞왼쪽", 6);
Tire frontRightTire = new Tire("앞오른쪽", 2);
Tire backLeftTire = new Tire("뒤왼쪽", 3);
Tire backRightTire = new Tire("뒤오른쪽", 4);
}
Class Car {
Tire[] tires = {
new Tire("앞왼쪽", 6),
new Tire("앞오른쪽", 2),
new Tire("뒤왼쪽", 3),
New Tire("뒤오른쪽", 4)
};
}
7-7-4. 매개 변수의 다형성
메소드 호출시 상위 타입을 매개변수로 선언하면, 매개값으로 자식객체 사용시 자동 타입 변환이 발생
//Vehicle.java
public class Vehicle {
public void run() {
System.out.println("차량이 달립니다.");
}
}
//Bus.java
public class Bus extends Vehicle {
@Override
public void run() {
System.out.println("버스가 달립니다.");
}
}
//Taxi.java
public class Taxi extends Vehicle {
@Override
public void run() {
System.out.println("택시가 달립니다.");
}
}
//Driver.java
public class Driver{
public void drive(Vehicle vehicle) {
vehicle.run();
}
}
//DriverTest.java
public class DriverTest {
public static void main(String[] args) {
Driver driver = new Driver();
Bus bus = new Bus();
Taxi taxi = new Taxi();
driver.drive(bus); // 버스가 달립니다.
driver.drive(taxi); // 택시가 달립니다.
}
}
7-7-5. 강제 타입 변환 (Casting)
부모 타입을 자식 타입으로 강제로 변환하는 것으로 자식 타입이 부모타입으로 자동 변환한 후, 다시 자식 타입으로 변환할 때만 사용 가능
- 자식 타입을 부모 타입으로 자동 변환하면, 부모 타입에 선언된 필드, 메소드만 사용 가능하다는 제약 발생
- 자식 타입에 선언된 필드와 메소드를 사용해야 할 경우, 강제 타입 변환을 하여 자식 타입으로 변환한 후 사용 가능
//Parent.java
public class Parent {
public String field1;
public void method1() {
System.out.println("메소드1");
}
}
//Child.java
public class Child {
public string field2;
public void method2() {
System.out.println("메소드2");
}
}
//ChildTest.java
public class ChildTest {
public static void main(String[] args) {
Parent parent = new Child();
parent.field1 = '필드1';
parent.method1();
/* 불가능
parent.field2 = '필드2';
parent.method2();
*/
Child child = (Child) parent;
child.field2 = '데이터';
child.method2(); // 사용 가능
}
}
7-7-6. 객체 타입 확인 (instanceof)
어떤 객체가 어떤 클래스의 인스턴스를 확인하기 위해 instanceof 연산자 사용
- instanceof 연산자를 통해 매개값이 어떤 객체인지 확인 후 안전하게 강제 타입 변환을 사용해야 함
//Parent.java
public class Parent {}
//Child.java
public class Child extends Parent{
public static void main(String[] args) {
Parent parent = new Child();
Child child = (Child)parent;
System.out.println(parent instanceof Parent); //true
System.out.println(parent instanceof Child); //true
Parent p1 = new Parent();
//Child c1 = (Child) p1; 강제 타입 변환 불
System.out.println(p1 instanceof Parent); // true
System.out.println(p1 instanceof Child); // false
}
}