본문으로 바로가기

[Java] 다형성(Polymorphism)

category Language/Java 2020. 1. 18. 02:06

1. 다형성이란?

객체지향 개념에서 다형성이란 '여러 가지 형태를 가질 수 있는 능력'을 의미한다.

구체적으로 자바에서는 조상 클래스 타입의 참조변수로 자손 클래스의 인스턴스를 참조할 수 있는 것을 의미한다.

 

예제를 통해 보자면, 클래스 Tv와 CaptionTv는 상속관계에 있다.

//Parent class
class Tv{
    boolean power;
    int channe;
    
    voie power(){
    	power = !power;
    }
    void channelUp(){
    	++channel;
    }
    void channelDown(){
    	--channel;
    }
}

//child class
class CaptionTv extends Tv{
    String text;
    void caption(){
    // 내용 생략
    }
}

 

클래스의 인스턴스를 생성하고 사용할 때

인스턴스의 타입과 참조변수의 타입이 일치하는 것이 보통이지만

서로 상속관계에 있을 경우 조상 클래스 타입의 참조변수로 자손 클래스의 인스턴스를 참조하는 것이 가능하다.

// 보통 인스턴스 참조 시
Tv t = new Tv();
Caption c = new CaptionTv();

// 조상타입의 참조변수로 자손 인스턴스 참조
Tv t = new CaptionTv();

위의 예시처럼 실제 인스턴스가 CaptionTV타입이라 할지라도,

참조변수 t로는 CaptionTV인스턴스의 모든 멤버를 사용할 수 없다.

Tv타입의 참조변수로는 CaptionTv인스턴스 중에서 Tv클래스의 멤버들만 사용할 수 있는 것이다.

 

즉, 둘 다 같은 타입의 인스턴스지만 참조변수의 타입에 따라 사용할 수 있는 멤버의 개수가 달라진다.

 

  • 반대로 자손타입의 참조변수로 조상타입의 인스턴스를 참조하는 것은 불가능 하다.
  • 참조변수가 사용할 수 있는 멤버의 개수는 인스턴스의 멤버 개수보다 같거나 적어야 한다.

2. 참조변수의 형변환

기본형 변수와 같이 참조변수도 형변환이 가능하다.

단, 서로 상속관계에 있는 클래스사이에서만 가능하다.

 

  • 자손타입 -> 조상타입(Up-casting) : 형변환 생략가능.
  • 자손타입 <- 조상타입(Down-casting) : 형변환 생략불가

참조변수간의 형변환도 캐스트 연산자를 사용하며, 괄호()안에 변환하고자 하는 타입의 이름(클래스명)을 적어주면 된다.

 

형변환은 참조변수의 타입을 변환하는 것이지 인스턴스를 변환하는 것은 아니기 때문에

참조변수의 형변환은 인스턴스에 아무런 영향을 미치지 않는다.

단지 참조변수의 형변환을 통해서, 참조하고 있는 인스턴스에서 사용할 수 있는 멤버의 범위(개수)를 조절하는 것이다.

 

예제 코드)

class CastingTest1 {
    public static void main(String args[]) {
        Car car = null;  // Car타입의 참조변수 car를 선언하고 null로 초기화한다.
        FireEngine fe = new FireEngine();  // FireEngine인스턴스를 생성하고 FireEngine타입의 참조변수가 참조하도록 한다.
        FireEngine fe2 = null;

        fe.water();
        car = fe;               // car = (Car)fe;에서 형변환이 생략된 형태다. fe가 참조하고 있는 인스턴스의 주소가 car에 저장된다. 
        fe2 = (FireEngine)car;  // 자손타입 <- 조상타입, car에는 FireEngine인스턴스의 주소가 저장되어 있으므로 fe2에도 FireEngine인스턴스의 주소가 저장된다. car와는 달리, fe2는 FireEngine타입이므로 FireEngine인스턴스의 모든 멤버들을 사용할 수 있다.
        fe2.water();
    }
}

class Car {
    String color;
    int door;

    void drive() {
        System.out.println("drive, Brrrr~");    
    }
    void stop() {
        System.out.println("stop!!!");
    }
}

class FireEngine extends Car {
    void water() {
        System.out.println("water!!!");
    }
}

서로 상속관계에 있는 타입간의 형변환은 양방향으로 자유롭게 수행될 수 있으나,

참조변수가 가리키는 인스터스의 자손타입으로 형변환은 허용되지 않는다.

그래서 참조변수가 가리키는 인스턴스의 타입이 무엇인지 확인하는 것이 중요하다.

'Language > Java' 카테고리의 다른 글

[Java] 추상클래스(abstract class)  (0) 2020.01.18
[Java] 제어자  (0) 2020.01.18
[Java] 상속(Inheritance)  (0) 2020.01.18
[Java] 오버로딩과 오버라이딩  (0) 2020.01.17
[Java] 클래스와 객체  (0) 2020.01.15