다형성(Polymorphism)

syeon·2022년 1월 13일
0

Java

목록 보기
3/4

다형성

다형성은 다양한 형태 또는 특성을 갖는다는 의미이다.
Java 객체 지향 프로그래밍에서는 부모클래스를 상속 받는 자식클래스의 인스턴스가 부모의 객체로도 사용되고, 자식클래스의 객체로도 사용될 수 있는 다양한 상황을 의미한다.

🤔 다형성을 활용한 객체 생성 방법?

다형성은 상속(extends)을 통해서 구현이 가능하다.
아래 코드를 보면 부모클래스 Bird가 있고, 이를 상속 받는 자식클래스 Parrot이 있다.

class Bird {
    String name = "새";
    void method1() { System.out.printf("%s이다.%n", name); }
    void bird_method() { System.out.println("부모 클래스 Bird"); }
}

class Parrot extends Bird {
    String name = "앵무새";
    String bird_name = "앵무새";
    void parrot_method() { System.out.println("자식 클래스 Parrot"); }

    @Override
    void method1() {
        System.out.println(System.out.printf("새의 종류는 %s이다.%n", bird_name));
    }
}

두 클래스를 활용하여 네 가지 방법으로 객체를 생성해보자.

객체 생성 [1] : 부모 + 자식 클래스의 모든 자원 사용 가능

Parrot 타입의 객체 parrot1은 너무나 당연하게도 상속 받은 부모클래스의 자원과 본인(자식클래스)의 자원 모두 이용이 가능하다.

Parrot parrot1 = new Parrot();

Parrot parrot1 = new Parrot();
System.out.println(parrot1.name);
System.out.println(parrot1.bird_name);
parrot1.method1();
parrot1.parrot_method();
parrot1.bird_method();
-----------------------------------------
> 앵무새
> 앵무새
> 새의 종류는 앵무새이다.
> 자식 클래스 Parrot
> 부모 클래스 Bird

이때 상속 받은 메서드 method1과 String 변수 name의 경우 자식클래스에서 오버라이드한 형태로 출력되는 것을 알 수 있다.
그렇다면 Parrot클래스에서는 method1의 원본 "새이다."를 출력할 수 없는 걸까?

🤔 만약 자식클래스에서 오버라이드된 부모클래스의 원본 자원을 호출하고 싶다면? ---> super 키워드 사용

super 키워드를 사용하면 자식클래스에서도 원본 메서드의 이용이 가능하다.

class Bird {
    String name = "새";
    void method1() { System.out.printf("%s이다.%n", this.name); }
    ...
}

class Parrot extends Bird {
	...
    void method2() {
        super.method1();
        System.out.println(super.name);
    }
}
public class Main {
	public static void main(String[] args) {
    	Parrot parrot = new Parrot();
        parrot1.method2();
    }
}
-----------------------------------------------------------------
>> 새이다.
>>

Parrot클래스에 부모클래스 Bird의 메서드 method1과 변수 name을 super키워드로 받은 후, 이들을 출력하는 메서드 method2를 만들어주었다. super 키워드로 받은 값은 부모클래스의 원본 값 그대로 출력됨을 확인할 수 있다.

객체 생성 [2] : 부모클래스의 모든 자원 사용 가능

너무나 당연하게도 Bird 타입의 객체 bird1도 Bird클래스의 자원을 이용할 수 있다.
그리고 또 너무나 당연하게도 자식 클래스의 자원은 이용할 수 없다.

Bird bird1 = new Bird();

Bird bird1 = new Bird();
System.out.println(bird1.name);
bird1.method1();
bird1.bird_method();
------------------------------------
>> 새이다.
> 부모 클래스 Bird

객체 생성 [3] : 부모클래스의 자원만 사용 가능?

그렇다면 타입은 부모클래스(Bird)이되, 자식클래스(Parrot)로 bird2객체를 생성해보자.
bird2의 타입이 부모클래스이기 때문에 부모클래스, Bird의 자원은 사용이 가능하다.

Bird bird2 = new Parrot();

Bird bird2 = new Parrot();
System.out.println(bird2.name);
// System.out.println(bird2.bird_name); >> Error! 자식클래스의 자원 사용 못함
bird2.method1();
bird2.bird_method();
// bird2.parrot_method();               >> Error! 자식클래스의 자원 사용 못함
------------------------------------
>> 새의 종류는 앵무새이다.
> 부모 클래스 Bird

여기서 두 가지 흥미로운 점을 볼 수 있다.

  • 자식 클래스의 자원은 이용할 수 없다.
  • 상속 받는 메서드의 경우 자식클래스의 것을 실행된다.

정말 부모클래스 타입 + 자식클래스로 생성 의 경우에는 오버라이드된 자식클래스의 메서드외에는 부모클래스의 자원만 사용 가능한 것일까?

🤔 만약 자식클래스의 자원을 사용하고 싶다면? ---> 형 변환!

bird2의 타입을 자식클래스(Parrot)로 강제 형 변환을 하면 자식클래스의 자원에도 접근이 가능하다!

((Parrot)bird2).parrot_method();
System.out.println(((Parrot) bird2).bird_name);
------------------------------------------------
>> 자식 클래스 Parrot
>> 앵무새

객체 생성 [4] : 부모클래스 객체 생성시 자식 타입으로 생성 불가!

앞서 본 객체 생성 방식[3]과 반대로
자식클래스 타입 + 부모클래스로 생성은 불가능하다.

Parrot parrot2 = new Bird(); >> Error!

정리

정리하면, 하위클래스의 인스턴스(객체)는 상위클래스의 인스턴스로도 사용될 수 있다. 하지만 반대로 성립될 수 없다.
왜냐하면 앵무새(Parrot class)는 그 상위인 새(Bird class)라고 말할 수 있지만, 모든 새가 앵무새는 아니기 때문이다! 따라서 상위(부모)클래스의 인스턴스는 하위(자식)클래스의 인스턴스로 사용될 수 없다.

profile
기록하려고 만든 개발블로그, 까먹지 말자!

0개의 댓글