다형성의 의미와 무늬 vs 실체 (008-002~004)

전제 클래스 (아래 문제 공통)

public class Animal {
	public void shout() {
		System.out.println("...");
	}
}
 
public class Dog extends Animal {
	@Override
	public void shout() {
		System.out.println("Woof");
	}
}
 
public class Cat extends Animal {
	@Override
	public void shout() {
		System.out.println("Meow");
	}
}

다음 코드의 출력은?

Animal[] animals = new Animal[] { new Dog(), new Animal(), new Cat() };
 
for (Animal animal : animals) {
	animal.shout();
}
Woof
...
Meow
  • 원칙: 실행되는 구현은 변수의 자료형(무늬)이 아니라 실행 중 실제 개체의 자료형(실체) 기준
  • new Animal()은 실체가 부모형이므로 부모 구현이 실행됨
  • 부모형 배열에 다른 종류의 개체를 담아 같은 지시를 내리는 것 — 상속 덕분에 가능

다음 코드의 출력은? (캐스팅 함정)

Dog dog = new Dog();
Animal animal = (Animal) dog;
animal.shout();

Woof

  • 부모형으로 캐스팅해도 바뀌는 것은 무늬뿐 — 실체는 여전히 Dog라 자식 구현이 실행됨
  • 본질: 캐스팅은 개체를 바꾸는 게 아니라 컴파일러가 보는 타입을 바꾸는 것 (컴파일러와의 협업) — 업캐스트는 무늬를 넓혀 검사 없이 통과, 다운캐스트는 무늬를 좁히므로 실체가 맞는지 런타임 검사(ClassCastException)로 미뤄짐
    • 컴파일러의 판정 기준은 가능성: 실행 중 호환 가능성이 0%면(형제 관계 등) 컴파일 오류로 차단, 가능성이 있으면 통과시키고 실체 대조는 런타임에 위임 — 상속과 명시적 캐스팅 참고
  • 오버라이딩된 부모의 원래 구현을 호출하는 방법은 두 가지뿐
    1. 자식 클래스 안에서 super.shout() 호출
    2. 실행 중 개체 자체가 부모형인 경우 — new Animal().shout()

animal.shout() 호출에서 컴파일 중에 결정되는 것과 실행 중에 결정되는 것은?

  • 컴파일 중: 함수 시그니처 — 변수 자료형(Animal)에 shout() 시그니처가 존재하는지 (없으면 컴파일 오류)
  • 실행 중: 실제로 어떤 함수 구현이 실행되는지 — 실체의 자료형 기준 (late binding)

다형성을 구현하려면 왜 상속이 필요한가? (5문장 이내)

다형성은 다른 종류의 개체에 같은 지시를 내리면 동작을 달리하는 것임. “같은 지시”는 동일한 함수 시그니처 호출을 뜻하므로 모든 종류가 공유하는 시그니처가 필요하고, 그 시그니처가 놓이는 곳이 부모 클래스임(무늬). “다른 종류의 개체”에 지시하려면 부모형 변수 하나가 여러 자식 실체를 참조할 수 있어야 하는데, 이 대입을 허용하는 관계가 상속(is-a)임. “동작을 달리”는 자식이 시그니처를 유지한 채 바디만 덮어쓰는 오버라이딩으로 구현되고, 실행 중 실체 기준으로 선택됨(late binding). 결국 정의의 세 요소가 각각 상속을 전제로 함.

  • 컴파일러 관점 보강: 호출부(animal.shout())가 컴파일되려면 컴파일러가 무늬(부모형)에서 시그니처의 존재를 확인할 수 있어야 함 — 상속이 그 보장을 제공
  • 전개 순서 기억법: 정의 3요소(“같은 지시” → 공유 시그니처 = 부모 / “다른 종류” → 부모형 변수에 자식 대입 = is-a / “다른 동작” → 오버라이딩 + late binding) 각각을 상속 요구로 번역

다형성이 없는 절차적 언어에서는 “종류마다 다른 동작”을 어떻게 처리하며, 무엇이 불편한가?

if 문(타입 분기)으로 처리

  • 종류를 판단하는 중재자 코드가 필요하고, 새로운 종류가 추가될 때마다 분기문을 고쳐야 해서 불편함

강의에서 말하는 OOP의 다형성은 정확히 무엇인가?

서브타입 다형성(subtype polymorphism)

  • “다른 종류의 개체”(타입이 다름)에 “같은 지시”(동일한 함수 시그니처 호출)를 내리면 “동작을 달리”(실행되는 구현이 다름) 하는 것

0건의 항목