다형성은 상속과 유사/밀접한 관계가 많아 part12와 함께 보는 것을 추천한다.
비슷한 이유로, 상속 부분에서 작성한 코드를 활용하여 학습을 진행한다.
다형성을 알기 전에 우리는 집합의 개념을 먼저 알고 넘어가야 한다.
생명체의 조건이 '숨을 쉰다' 라고 한다면, 그의 하위 범위인 동물은 '움직일 수 있다', 식물은 '움직일 수 없다' 라는 조건이 붙을 수 있다.
이때, 동물과 식물에는 생명체의 조건인 '숨을 쉰다' 에 추가로 조건이 붙는 것이다.
=> 조건이 더 많고 구체적일 수록 좁은 집합이다.
이 집합의 구조를 part 상속에서 만들었던 Animal 에 빗대보자.
Animal 클래스는 Print() 의 기능만 가지고 있다. 하지만 Animal 을 상속받은 Cat 과 Dog 은 각각 Print() 와 더불어 Stealth() / Hunt() 의 기능을 가지고 있게 된다.
Animal 보다 더 구체적인 Cat와 Dog이라는 클래스인 만큼 더 많은 기능, 더 많은 조건을 가지고 있는 것이다.
이때 서로를 표현하는 방식에 관해서는 Cat 과 Dog은 Animal 이라고 부를 수 있지만, Animal 은 Cat 과 Dog이라고 장담할 수 없다.
코드 : 이전 코드에 이어서 작성
//Test 클래스에 이어서 작성
Animal someAnimal = jack;
someAnimal.Hunt();
someAnimal.Print();
해당 코드를 작성하면 someAnimal.Hunt() 는 오류, someAnimal.Print()는 정상 작동한다.
이유가 무엇일까?
바로 "객체를 무엇으로 다루느냐" 의 차이이다.
위에서 언급한 서로를 표현하는 방식과 같은 이유로, Animal 을 Cat과 Dog으로 부를 수 없다는 것이다.
'jack' 자체는 Dog의 정보를 가지고 있지만, someAnimal 은 Animal 로 취급하기 때문에 Dog의 기능을 사용할 수 없다.
하지만 그렇다고 Dog의 정보가 사라진 것은 아니다. 다만 다룰 수 없는 것 뿐이다.
코드 추가
Dog myDog = (Dog)someAnimal;
myDog.Hunt();
Animal 로 다루고 있던 someAnimal 을 다시 Dog로 취급하는 'myDog' 에 대입해주었더니, Hunt()를 사용하는데 에러가 발생하지 않게 됐다.
someAnimal 은 'jack' 의 기능을 사용하지 못할 뿐 정보는 가지고 있기 때문에,
Dog 객체로 다룰 때 그 정보를 다시 사용할 수 있게 되는 것이다.
(Dog)someAnimal
someAnimal 은 Animal 로서 취급되고 있는데, 이 정보를 더 좁은 집합인 Dog로 할당하기 위해서는
명시적 형변환 을 해주어야 한다.
이와 같은 과정을 통해 Cat 과 Dog은 부모 클래스인 Animal 의 특성을 모두 가지고 있다는 것을 확인하였다.
=> 같은 특성을 가지고 있다는 것은 Animal 로서 일괄 처리가 가능하다는 것이다.
코드
Animal[] animals = new Animal[2];
animals[0] = nate;
animals[1] = jack;
for (int i = 0; i < animals.Length; i++)
{
animals[i].Print();
}
Cat 인 'nate' 와 Dog 인 'jack' 을 Animal 배열에 할당하여 반복문으로 처리하였다.
실행 결과
Cat과 Dog이 모두 가지고 있는 Animal의 기능, Print()를 사용했기에 정상적으로 일괄 처리가 가능한 것이다.
1. 부모 클래스로부터 파생된 객체들은 공통된 특성을 가지고 있다.
2. 부모 객체의 특성에서 자신의 특성을 덧붙일 수 있다.
3. 자식 객체들을 공통된 부모 객체로 일괄처리 할 수 있다.
#15. 인터페이스(Interface) (0) | 2024.08.05 |
---|---|
#14. 오버라이드(Override) (0) | 2024.08.03 |
#12. 상속 심화 (0) | 2024.08.02 |
#11. 레이캐스트(RayCast) (0) | 2024.08.01 |
#10. 코루틴(Coroutine) (0) | 2024.07.31 |