Programming/Java

[Java 자바] 7. 상속 ② 타입 변환과 다형성, instanceof

erinh 2022. 8. 7. 23:50
반응형

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
  }
}
반응형