[Java] 상속 : 타입 변환, 다형성

Local Gaji·2023년 8월 15일

이것이 자바다

목록 보기
7/18

🎈 자동 타입 변환

넓은 범위의 타입 변수에 좁은 타입의 값이 대입되면 자동 타입 변환이 일어난다.

byte small = 10;
int big = small;
// small 의 type 이 byte 로 자동 변환됨

마찬가지로 넓은 객체 타입 변수에 좁은 객체가 대입되면,
좁은 객체의 타입은 넓은 객체 타입으로 자동 변환된다.

이때 넓은 범위 객체는 조상 클래스, 좁은 범위 객체는 자손 클래스이다.

부모타입 변수 = 자식타입객체;

Child child = new Child(); 
Parent parent = child;
// child 변수에 저장된 Child 객체의 타입이 Parent로 변환된다.

Animal animal = new Cat();
// Cat 객체가 생성되고 타입이 Animal 로 변환된다.

child 변수와 parent 변수는 타입이 다르지만, 동일한 Child 객체를 참조하고 있다. (cat == animal)


🔰 자동 타입 변환된 객체의 메서드

자동 타입 변환된 변수는 자손 객체의 주소를 저장한다.
따라서 메서드 호출 시, 자손 객체에서 오버라이딩 한 버전으로 호출된다.

하지만 타입이 조상객체 타입이므로, 부모 클래스에 있는 멤버에만 접근할 수 있다.

class Parent {
  void method1() { ... }
  void method2() { ... }
}

class Child {
  void method2() { ... }  // overide
  void method3() { ... }
}

class Example {
  public static void main (String[] args) {
    Parent parent = new Child();
    
    parent.method1();   // 호출 O
    parent.method2();   // 호출 O (overide 버전)
    parent.method3();   // 호출 X (parent 객체의 멤버가 아니므로)
  }
}

🎈 강제 타입 변환

좁은 타입 변수에 넓은 객체를 대입할 때에는 캐스팅 연산자를 사용해서 타입을 강제로 변환한다.

자식 객체를 부모 타입으로 자동 변환한 후, 다시 자식 타입으로 변환하고 싶을 때에만 강제 타입 변환이 가능하다.

자식타입 변수 = (자식타입) 부모타입객체;

Parent parent = new Child();    // 부모타입으로 자동변환
Child child = (Child) parent;   // 자식타입으로 강제 변환

자식 객체를 부모 타입으로 자동 변환했기 때문에, 자식 객체에만 있는 메서드는 사용하지 못했다.
하지만 자식 객체에만 있는 메서드를 꼭 사용해야 한다면, 강제 타입 변환을 이용해 자식 타입으로 다시 변환해야한다.


🎈 다형성

사용 방법은 같은데 실행 결과는 다르게 나오는 성질

부모 객체의 자식 객체인 객체 A객체 B가 있을 때, 자식 객체들이 부모 객체의 메서드를 오버라이딩 했다면, 실행 결과는 다르게 나올 수 있다.


🔰 필드 다형성

/* CPU.java */
public class CPU {
  public void powerOn() {
    System.out.println("CPU 전원 ON");
  }
}


/* Intel.java */
public class Intel extends CPU {
  public void powerOn() {
    System.out.println("Intel CPU 전원 ON");
  }
}


/* AMD.java */
public class AMD extends CPU {
  public void powerOn() {
    System.out.println("AMD CPU 전원 ON");
  }
}

외부의 Desktop 객체에서 CPU 객체를 생성하고, CPU 객체의 powerOn() 메서드를 사용한다.

/* Desktop.java : CPU 객체 사용 */
public class Desktop {
  /* cpu 필드 선언 */
  public CPU cpu;    
  
  /* start 메서드 선언 */
  public void start() {
    cpu.powerOn();
  }
}

cpu 필드 : Inter , AMD 객체가 대입된다.
start 메서드 : cpu 필드에 대입된 각 객체마다 오버라이딩 된 powerOn 메서드를 가지고 있을 수 있다. 이때 실행 결과는 달라질 수 있다.



/* Example.java : 실행하기 */
public class Example {
  public static void main(String[] args) {
    Desktop pc1 = new Desktop();
    
    /* CPU 객체 생성 */
    pc1.cpu = new CPU();
    pc1.start();             //       CPU 전원 ON
    
    /* Intel 객체 생성 */
    pc1.cpu = new Intel();  
    pc1.start();             // Intel CPU 전원 ON
    
    /* AMD 객체 생성 */
    pc1.cpu = new AMD();
    pc1.start();             //   AMD CPU 전원 ON
    
  }
}

🔰 매개변수 다형성

메서드가 클래스 타입의 매개변수를 가지고 있는 경우가 있다.

Desktop.java 파일에서, CPU 객체 타입의 필드를 선언하고, 이 객체의 메서드인 powerOn() 을 실행시켜주는 메서드 start 를 작성했다.


하지만 아래와 같이 필드를 따로 선언하지 않고, CPU 타입 객체를 매개변수로 받을 수 있다.

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

start 메서드를 호출할 때, CPU 객체를 매개변수로 전달하고싶다면 생성해서 전달하면 된다.

Desktop pc1 = new Desktop();
CPU cpu = new CPU();
pc1.start(cpu);

하지만 CPU 의 자식 객체인 Intel , AMD 객체를 매개변수로 전달하고 싶다면, 자동 타입 변환을 활용해야 한다. 매개변수 타입은 CPU 로 지정되어 있기 때문이다.

매개변수에 자식 객체를 전달하는 과정에서 자동 타입 변환이 일어나게 된다.

/* Example.java : 실행하기 */
public class Example {
  public static void main(String[] args) {
    Desktop pc1 = new Desktop();
    
    Intel intel = new Intel();  
    pc1.start(intel);  // 타입 변환
    
    AMD amd = new AMD();  
    pc1.start(amd);    // 타입 변환
  }
}

🎈 객체 타입 확인

변수나 매개변수가 참조하는 객체의 타입을 확인하고 싶다면 instanseof 연산자를 사용한다.

boolean result = 객체변수 instanseof 객체타입

매개변수로 받은 객체가 자식 타입에서 부모타입으로 자동 변환 된건지 확인하고, 다시 자식타입으로 강제 변환 해주고 싶을 경우,

void method(Parent parent) {
  if(parent instanceof Child) {
    Child child = (Child) parent;
    // child 변수 사용
  }
}

위와 같이 변환할 수도 있고, 우측 타입 변수를 사용할 수 있다.

void method(Parent parent) {
  if(parent instanceof Child child) {
    // child 변수 사용
  }
}













1개의 댓글

comment-user-thumbnail
2023년 8월 15일

좋은 글이네요. 공유해주셔서 감사합니다.

답글 달기