[Java] 다형성(Polymorphism)

Hoplin·2023년 1월 19일
0

다형성

객체지향 속성중 하나인 다형성에 대해서 알아보자. 다형성이란 여러가지 형태를 가질 수 있는 특성을 의미한다. 이는 한 타입의 참조변수로 여러 타입의 객체를 참조할 수 있도록 하는것을 의미한다.조금 더 구체적으로는 상속관계에서 해당 되는 이야기로, 조상 클래스 타입의 참조변수로 자손클래스 인스턴스를 참조할 수 있도록 하는것이다.

아래 예시를 한번 보자

class TV2{
    protected boolean power;
    protected int channel;

    TV2(){
        this.power = false;
        this.channel = 0;
    }
    void power(){
        this.power  = !this.power;
    }

    void channelUp(){
        ++this.channel;
    }

    void channelDonw(){
        --this.channel;
    }
}

class CaptionTV2 extends TV2{
    private String text;
    CaptionTV2(){
        super();
    }
    void caption(){
        System.out.println(text);
    }
}

class tvtest2{
    public static void main(String[] args){
        TV2 t = new CaptionTV2();
        CaptionTV2 t2 = new CaptionTV2();

        t.channelUp();
        t2.channelUp();

        t.caption(); // 에러가 난다.
        t2.caption();
    }
}

CaptionTV2 클래스의 인스턴스 두개를 생성하였다. 다만 하나는 참조변수 타입이 TV2이고 하나는 CaptionTV2인것이 차이점이다. 두개다 CaptionTV2의 인스턴스지만, t 참조변수는 .caption()메소드를 사용하지 못하는것을 볼 수 있다. 이는 둘다 같은 타입의 인스턴스지만, 참조변수 타입이 달라 접근 및 사용할 수 있는 멤버의 개수가 달라진것이기 때문이다.

자손 타입의 참조변수로 조상타입의 인스턴스를 참조하는것은 존재하지 않는 멤버를 사용하고자 할 가능성이 있으므로 허용하지 않는것이다. 결론적으로 참조변수가 사용할 수 있는 멤버의 개수는 인스턴스 멤버 개수보다 같거나 적어야 한다

Up-Casting, Donw-Casting

  • Up-Casting : 자손타입 -> 조상 타입, 형변환 생략이 가능하다
  • Down-Casting : 조상타입 -> 자손타입, 형변환 생략이 불가능하다.

위에서 보았던 개념중 t 참조변수는 결국 Up-Casting에 해당 한다. 그렇다면 Down-Casting의 개념은 어떻게 사용될까? 위의 개념만 본다면 아래와 같이 변경해줄 수 있다.

class TV2{
    protected boolean power;
    protected int channel;

    TV2(){
        this.power = false;
        this.channel = 0;
    }
    void power(){
        this.power  = !this.power;
    }

    void channelUp(){
        ++this.channel;
    }

    void channelDonw(){
        --this.channel;
    }
}

class CaptionTV2 extends TV2{
    private String text;
    CaptionTV2(){
        super();
    }
    void caption(){
        System.out.println(text);
    }
}

class tvtest2{
    public static void main(String[] args){
        TV2 t = new TV2();
        CaptionTV2 t2 = (CaptionTV2) t;
        t2.caption();
    }
}

컴파일은 잘 되는 코드인것을 확인하였다. 하지만 실행을 해보면, 오류가 나는것을 확인할 수 있다. 우선 Down-Casting은 조상클래스 타입 인스턴스를 자식클래스 타입 인스턴스로 변환하는것은 맞다. 하지만, 위 코드에서 t인스턴스는 처음부터 TV2클래스의 인스턴스로 생성이 되었다 그렇기 때문에 기본적으로 CaptionTV2 클래스에 있는 .caption()메소드를 가지고 있지 않다.

결론적으로 Down-Casting은 Up-Casting에 의해 접근범위를 제한당한 인스턴스의 사용 범위를 되돌릴때 사용한다. 이를 사용할때 instanceof연산자와 같이 사용하여 더욱 안전하게 Down-Casting을 진행해 줄 수 있다.

class TV2{
    protected boolean power;
    protected int channel;

    TV2(){
        this.power = false;
        this.channel = 0;
    }
    void power(){
        this.power  = !this.power;
    }

    void channelUp(){
        ++this.channel;
    }

    void channelDonw(){
        --this.channel;
    }
}

class CaptionTV2 extends TV2{
    private String text;
    CaptionTV2(String text){
        super();
        this.text = text;
    }
    void caption(){
        System.out.println(text);
    }
}

class tvtest2{
    public static void main(String[] args){
        TV2 t = new CaptionTV2("Example text");

        CaptionTV2 t2;
        if(t instanceof CaptionTV2){
            t2 = (CaptionTV2) t; // DownCasting은 형변환 생략이 불가능하다
            t2.caption();
        }
    }
}
profile
더 나은 내일을 위해 오늘의 중괄호를 엽니다

0개의 댓글