--- id: wiki-2026-0508-inheritance-and-polymorphism title: Inheritance and Polymorphism category: 10_Wiki/Topics status: verified canonical_id: self aliases: [OOP Inheritance, Subtype Polymorphism, Method Dispatch] duplicate_of: none source_trust_level: A confidence_score: 0.95 verification_status: applied tags: [oop, programming-language, type-theory, polymorphism] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: multi framework: oop --- # Inheritance and Polymorphism ## 매 한 줄 > **"매 inheritance 의 mechanism — polymorphism 의 outcome"**. 매 inheritance 의 code reuse + 매 is-a 의 subtype relationship; 매 polymorphism 의 same interface 의 different behavior. 매 modern 2026 의 view 의 "favor composition over inheritance" 의 default — Go/Rust 의 inheritance-free, but interface-polymorphism 의 universal. 매 LLM-generated code 의 over-inheritance 의 common antipattern. ## 매 핵심 ### 매 inheritance 의 종류 - **Single inheritance**: 매 one parent class (Java, Kotlin, C#). - **Multiple inheritance**: 매 N parents — diamond problem (C++, Python via MRO). - **Mixins / traits**: 매 horizontal composition (Rust traits, Scala traits, Python mixins). - **Prototype-based**: 매 object → object delegation (JavaScript, Lua). ### 매 polymorphism 의 종류 - **Subtype polymorphism**: 매 subclass 의 parent 의 substitute (Liskov LSP). - **Parametric polymorphism (generics)**: 매 type parameter — `List`. - **Ad-hoc polymorphism (overloading)**: 매 same name 의 different signatures. - **Row polymorphism**: 매 structural — TypeScript / OCaml 의 records. ### 매 응용 1. **Domain hierarchy**: 매 `Animal → Dog/Cat`. Often overused. 2. **Plugin architecture**: 매 `Plugin` interface + N implementations. 3. **AST transformation**: 매 `Visitor` pattern + node hierarchy. 4. **Strategy pattern**: 매 interchangeable algorithms via interface. ## 💻 패턴 ### 매 subtype polymorphism (Python ABC + Liskov) ```python from abc import ABC, abstractmethod class Shape(ABC): @abstractmethod def area(self) -> float: ... class Circle(Shape): def __init__(self, r: float): self.r = r def area(self) -> float: return 3.14159 * self.r ** 2 class Rectangle(Shape): def __init__(self, w: float, h: float): self.w, self.h = w, h def area(self) -> float: return self.w * self.h # Polymorphic use — caller knows nothing about concrete type def total_area(shapes: list[Shape]) -> float: return sum(s.area() for s in shapes) print(total_area([Circle(2), Rectangle(3, 4)])) # 24.566... ``` ### 매 composition over inheritance (modern preferred) ```python # ❌ Inheritance-heavy — fragile class Animal: def move(self): print("move") class Bird(Animal): def fly(self): print("fly") class Penguin(Bird): # Penguin 의 fly X — Liskov violation def fly(self): raise NotImplementedError # ✅ Composition-based — flexible from dataclasses import dataclass from typing import Protocol class Mover(Protocol): def move(self) -> str: ... @dataclass class Walker: def move(self) -> str: return "walk" @dataclass class Flyer: def move(self) -> str: return "fly" @dataclass class Animal2: name: str mover: Mover # plug in capability — no inheritance penguin = Animal2("Penguin", Walker()) sparrow = Animal2("Sparrow", Flyer()) print(penguin.mover.move(), sparrow.mover.move()) ``` ### 매 generic parametric polymorphism (TypeScript) ```typescript // Same code for any T function head(xs: T[]): T | undefined { return xs[0]; } const n: number | undefined = head([1, 2, 3]); const s: string | undefined = head(["a", "b"]); // Bounded generic — T must be Comparable interface Comparable { compareTo(other: T): number; } function max>(xs: T[]): T { return xs.reduce((acc, x) => x.compareTo(acc) > 0 ? x : acc); } ``` ### 매 trait-based polymorphism (Rust — no inheritance) ```rust trait Area { fn area(&self) -> f64; } struct Circle { r: f64 } struct Square { side: f64 } impl Area for Circle { fn area(&self) -> f64 { 3.14159 * self.r * self.r } } impl Area for Square { fn area(&self) -> f64 { self.side * self.side } } // Static dispatch (zero-cost generics) fn print_area_static(s: &T) { println!("{}", s.area()); } // Dynamic dispatch (vtable) fn print_area_dyn(s: &dyn Area) { println!("{}", s.area()); } fn main() { let shapes: Vec> = vec![ Box::new(Circle { r: 2.0 }), Box::new(Square { side: 3.0 }), ]; for s in &shapes { print_area_dyn(s.as_ref()); } } ``` ### 매 visitor pattern (AST traversal) ```python from dataclasses import dataclass from typing import Union # AST hierarchy @dataclass class Num: value: float @dataclass class Add: left: "Expr"; right: "Expr" @dataclass class Mul: left: "Expr"; right: "Expr" Expr = Union[Num, Add, Mul] # Polymorphic dispatch via match (Python 3.10+) def evaluate(e: Expr) -> float: match e: case Num(v): return v case Add(l, r): return evaluate(l) + evaluate(r) case Mul(l, r): return evaluate(l) * evaluate(r) # (3 + 4) * 5 print(evaluate(Mul(Add(Num(3), Num(4)), Num(5)))) # 35 ``` ### 매 LSP-violation 의 detector (mypy + tests) ```python # Runtime LSP check — for each subclass override, parameter contravariant + return covariant import inspect from typing import get_type_hints def check_lsp(parent: type, child: type) -> list[str]: issues = [] for name in dir(parent): if name.startswith("_") or not callable(getattr(parent, name)): continue try: p_hints = get_type_hints(getattr(parent, name)) c_hints = get_type_hints(getattr(child, name)) except Exception: continue # Return type must be subtype of parent's return if "return" in p_hints and "return" in c_hints: if not issubclass(c_hints["return"], p_hints["return"]): issues.append(f"{child.__name__}.{name}: return type widens parent") return issues ``` ## 매 결정 기준 | 상황 | Approach | |---|---| | 매 is-a 의 stable | Inheritance OK — keep depth ≤ 2 | | 매 has-a / can-do | Composition + protocol/interface | | 매 cross-cutting (logging, metrics) | Decorator / mixin / aspect | | 매 algorithm variants | Strategy pattern (composition) | | 매 type-safe collections | Parametric generics (`List`) | | 매 closed AST / variant data | Sum types + pattern match (Rust enum, Scala sealed) | **기본값**: 매 composition + interface — inheritance 의 only when 명확 is-a + LSP-honoring. ## 🔗 Graph - 부모: [[Object-Oriented-Programming]] · [[Type Theory]] - 변형: [[Subtype Polymorphism]] · [[Parametric Polymorphism]] - 응용: [[Visitor Pattern]] - Adjacent: [[Composition over Inheritance]] · [[Duck Typing]] ## 🤖 LLM 활용 **언제**: 매 boilerplate 의 generation (interface + N impls) / 매 LSP audit / 매 inheritance-to-composition refactor. **언제 X**: 매 deep inheritance design — 매 LLM 의 over-inherit 의 tendency. Manual review 필수. ## ❌ 안티패턴 - **매 deep inheritance**: 매 4+ levels — fragile base class problem. - **매 LSP violation**: 매 subclass 의 throws on parent-supported method (Penguin.fly). - **매 inheritance for code reuse only**: 매 not is-a — use composition. - **매 god parent class**: 매 parent 의 every responsibility — SRP violation. - **매 multiple inheritance 의 diamond ignore**: 매 MRO 의 surprise behavior. ## 🧪 검증 / 중복 - Verified (Gamma et al. *Design Patterns* 1994; Liskov & Wing *A Behavioral Notion of Subtyping* 1994; Effective Java Item 18 "Favor composition" 2018). - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — types of inheritance + polymorphism + multi-language patterns |