새소식

JAVA

자바 기초 : 타입 변환과 다형성

  • -

핵심개념

  • 타입변환 : 기본타입과 마찬가지로 클래스도 타입 변환이 있으며, 이를 활용하면 객체 지향프로그래밍의 다형성을 구현할 수 있다.

  • 다형성 : 사용 방법은 동일하지만 다양한 객체를 활용해서 여러 실행결과가 나오도록 하는 성질.
    ex) 자동차가 타이어를 사용하는 방법은 동일. but 어떤 타이어를 사용하느냐에 따라 주행성능이 달라짐.

    다형성을 구현하기 위해서는 메소드 재정의와 타입변환이 필요하다.
    ->   메소드 재정의 + 타입 변환 = 다형성

  • 자동 타입 변환 : 프로그램실행 도중 자동으로 타입 변환이 일어나는 것. 클래스의 변환은 상속관계에 있는 클래스 사이에서 발생하며, 자식은 부모 타입으로 자동 타입 변환이 가능하다. 이때, 바로 위의 부모가 아니더라도 상속계층에서 상위 타입인 경우 자동 타입변환이 일어날 수 있다.

자동타입변환

     ex) Cat 클래스가 Animal 클래스를 상속 받았을 경우
           Cat cat = new Cat();   //Cat 클래스로부터 Cat 객체를 생성
           Animal animal = cat;  //Animal 변수에 대입 -> 자동타입변환이 일어남

 
class A{}
class B extends A{}
class C extends A{}
class D extends B{}
class E extends C{}

public class PromotionEx {
public static void main(String[] args) {
   B b = new B();
   C c = new C();
   D d = new D();
   E e = new E();

   //모두 A를 상속받고 있기 때문에 자동타입변환 가능
   //A - B - D
   //A - C - E
   A a1 = b;
   A a2 = c;
   A a3 = d;
   A a4 = e;

   B b1 = d;
   C c1 = e;

   //B b2 = e;(x)
   //C c2 = d;(x)
   }
}

 

  • 자동타입 변환 후의 멤버 접근 : 부모 타입으로 자동타입 변환된 이후에는 부모 클래스에 선언된 필드 및 메소드만 접근이 가능하다. 하지만 예외적으로 메소드가 자식 클래스에 재정의 될 경우에는 자식 클래스의 메소드가 대신 호출된다.
public class Parent {
   public void method1() {
     System.out.println("Parent-method1()");
   }
   public void method2() {
      System.out.println("Parent-method2()");
   }
}

---------------------------------------------------------

public class Child extends Parent{
   @Override
   public void method2() {
      System.out.println("Child-method2()"); //재정의
   }
   public void method3() {
      System.out.println("Child-method3()");
   }
}

---------------------------------------------------------

public class ChildEx {
   public static void main(String[] args) {
   Child child = new Child();

   Parent parent = child;
   parent.method1();
   parent.method2();
   /*메소드 이름이 부모클래스에 있는것 같으나
   실제 실행은 재정의된 자식클래스에 있는 메소드가 실행됨.*/

   //parent.method3(); (x)
   /*Child 객체는 method3()메소드를 가지고 있지만.
   Parent 타입으로 자동변환된 이후에는 method3()를 호출할 수 없다.*/
   
   parent = new Parent();
   parent.method2();
   }
}
실행결과 : 
Parent-method1()
Child-method2()
Parent-method2()

 

  • 필드의 다형성 : 필드 타입을 부모 타입으로 선언할 경우, 다양한 자식 객체가 저장되어 필드 사용결과가 달라지는 것. 자동타입변환이 필요한 이유는 다형성을 구현하기 위해서이다.
    부모 클래스를 상속하는 자식클래스는 부모가 가지고 있는 필드와 메소드를 가지고 있으므로 사용 방법은 동일하다. 자식 클래스는 부모의 메소드를 재정의하여 메소드의 실행 내용을 변경함으로써 더 우수한 실행결과가 나오게할 수 있다. 
public class Tire {
   public void roll() {
      System.out.println("타이어가 굴러 갑니다.");
   }
}

------------------------------------------------------------------

public class HanTire extends Tire{
   @Override
   public void roll() {//메소드 재정의. 출력내용변경
      System.out.println("Han 타이어가 굴러갑니다.");
   }
}

------------------------------------------------------------------

public class KumTire extends Tire {
   @Override
   public void roll() {//메소드 재정의. 출력내용변경
      System.out.println("Kum 타이어가 굴러갑니다.");
   }
}

------------------------------------------------------------------

public class Car {
   //필드 자동차는 4개의 타이어를 가진다.
   Tire frontLeftTire = new Tire();
   Tire frontRightTire = new Tire();
   Tire backLeftTire = new Tire();
   Tire backRightTire = new Tire();

   //메소드
   void run() {
   frontLeftTire.roll();
   frontRightTire.roll();
   backLeftTire.roll();
   backRightTire.roll();
   }
}

------------------------------------------------------------------

public class CarEx {
   public static void main(String[] args) {
   Car car = new Car(); //Car객체 생성
   car.run();
   System.out.println();

   car.frontLeftTire = new HanTire();
   car.frontRightTire = new HanTire();
   car.backLeftTire = new KumTire();
   car.backRightTire = new KumTire();
   car.run();
   }
}
실행결과 : 
타이어가 굴러 갑니다.
타이어가 굴러 갑니다.
타이어가 굴러 갑니다.
타이어가 굴러 갑니다.

Han 타이어가 굴러갑니다.
Han 타이어가 굴러갑니다.
Kum 타이어가 굴러갑니다.
Kum 타이어가 굴러갑니다.

 

  • 매개 변수의 다형성 : 매개값으로 어떤 자식 객체가 제공되느냐에 따라 메소드의 실행결과가 다양해질 수 있다는 것. 매개변수를 부모 타입으로 선언하는 효과. 메소드 호출 시 매개 변수의 타입과 동일한 매개값을 가지는 것이 정석적이지만, 매개값을 다양화하기위해 매개 변수에 자식 객체를 지정할 수 있다.
    -> 부모 객체 및 모든 자식 객체를 제공할 수 있음. 자식의 재정의된 메소드가 호출됨.
public class Vehicle {
   public void run() {
      System.out.println("차량이 달립니다.");
   }
}

----------------------------------------------------------

public class Bus extends Vehicle{
   @Override
   public void run() {//run()메소드 재정의
     System.out.println("버스가 달립니다.");
   }
}

----------------------------------------------------------

public class Taxi extends Vehicle {
   @Override
   public void run() {//run()메소드 재정의
      System.out.println("택시가 달립니다.");
   }
}

----------------------------------------------------------

public class Driver {
   //drive()메소드에서 Vehicle 타입의 매개값을 받아 run()메소드를 호출
   public void drive(Vehicle vehicle) {
   //매개변수에 어떤 객체가 들어오느냐에 따라 메소드의 실행결과가 다양해짐.
   vehicle.run();
   }
}

----------------------------------------------------------

public class DriverEx {
   public static void main(String[] args) {
   //객체 생성
   Driver driver = new Driver();

   Vehicle vehicle = new Vehicle();
   Bus bus = new Bus();
   Taxi taxi = new Taxi();
   //Driver 객체의 driver()메소드 호출. 다양한 객체 제공.
   driver.drive(vehicle);
   driver.drive(bus);//자동타입변환 발생: Vehicle vehicle = bus;
   driver.drive(taxi);//자동타입변환 발생: Vehicle vehicle = taxi;
   }
}
실행결과 : 
차량이 달립니다.
버스가 달립니다.
택시가 달립니다.

 

  • 강제타입변환(casting) : 부모 타입을 자식 타입으로 변환하는 것. 언제나 변환할 수 있는 것은 아니고, 자식 타입이 부모 타입으로 자동 타입 변환한 후에 다시 자식타입으로 변환할 때 강제 타입 변환을 사용할 수 있다.
    자식 타입이 부모 타입으로 자동 타이변환되면, 부모에 선언된 필드와 메소드만 사용 가능.
    자식에 선언된 필드와 메소드를 사용해야할 경우 강제 타입 변환을 해서 필드와 메소드 사용 가능.

강제 타입 변환

       ex)Parent parent = new Child(); //자동타입변환

            Child child = (Child) parent; //강제타입변환

public class Parent {
   public String field1;
   public void method1() {
      System.out.println("Parent-method1()");
   }
   public void method2() {
      System.out.println("Parent-method2()");
   }
}

-----------------------------------------------------------

public class Parent {
   public String field1;
   public void method1() {
      System.out.println("Parent-method1()");
   }
   public void method2() {
      System.out.println("Parent-method2()");
   }
}

-----------------------------------------------------------

public class ChildEx {
   public static void main(String[] args) {
      Parent parent = new Child();
      //부모타입 변수 = 자식타입; -> 자동타입변환
      parent.field1 = "data1";
      parent.method1();
      parent.method2();

      //parent.field2 = "data2";
      //parent.method3();
      //Child에 있는 메소드를 사용하기 위해 강제타입변환 필요

      Child child = (Child)parent;
      //자식타입 변수 = (자식타입)부모타입; -> 강제타입변환
      child.field2 = "yyy";
      child.method3();
   }
}
실행결과 : 
Parent-method1()
Parent-method2()
Child-method3()

 

  • 객체 타입 확인 : 부모 변수가 참조하는 객체가 자식 객체인지 확인하는 방법. 어떤 객체가 어느 클래스의 인스턴스인지 확인하기 위해 instanceof연산자 사용. 연산자의 좌항에는 객체, 우항에는 타입. 좌항의 객체가 우항의 인스턴스이면(우항의 타입으로 객체 생성하였다면) true를 리턴.
    ex) boolean result = 좌항(객체) instanceof 우항(타입)
    ex) Parent parent = new Parent();
          Child child = (Child)parent; //강제타입변환할 수 없음.
public class Parent {
}

----------------------------------------------

public class Child extends Parent{
}

----------------------------------------------

public class InstanceOfEx {
   public static void method1(Parent parent) {//Parent타입의 매개값을 받음
      if(parent instanceof Child) {//parent가 Child의 인스턴스이면
         Child child = (Child)parent;
         System.out.println("method1 - Child로 변환 성공");
      }else {
         System.out.println("method1 - Child로 변환되지 않음");
      }
}

public static void method2(Parent parent) {//Parent타입의 매개값을 받음
   Child child = (Child)parent;
   /*ClassCastException 발생
   -> 변환이 가능한지 확인하지 않고 변환하였기 떄문*/
   System.out.println("method2 - Child로 변환 성공");
}

public static void main(String[] args) {
   Parent parentA = new Child();
   method1(parentA); //Child객체를 매개값으로 전달
   method2(parentA);

   Parent parentB = new Parent();
   method1(parentB); //Parent객체를 매개값으로 전달
   method2(parentB);
}
}
실행결과 : 
method1 - Child로 변환 성공
method2 - Child로 변환 성공
method1 - Child로 변환되지 않음
Exception in thread "main" java.lang.ClassCastingException

 

'JAVA' 카테고리의 다른 글

자바 기초 : 추상 클래스  (0) 2023.03.13
자바 기초 : 상속  (0) 2023.03.11
자바 기초 : 패키지와 접근 제한자  (0) 2023.03.08
자바 기초 : 인스턴스 멤버와 정적 멤버  (0) 2023.03.07
자바 기초 : 메소드  (0) 2023.03.06
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.