C#에서 오버라이딩(Overriding)과 섀도잉(Shadowing)은 모두 상속 관계에 있는 클래스에서 부모 클래스의 메서드를 다루는 기법이지만, 동작 방식과 용도가 확연히 다릅니다. 두 개념을 혼동하면 예상치 못한 버그를 유발할 수 있으므로, 각각의 특징을 정확히 이해하는 것이 중요합니다.
오버라이딩과 섀도잉의 주요 차이점
1. 재정의 범위의 차이
섀도잉은 부모 클래스의 메서드 전체를 새롭게 다시 정의하는 반면, 오버라이딩은 메서드의 시그니처는 그대로 유지한 채 구현 내용만 다시 작성합니다.
2. 부모 클래스 멤버 접근 여부
오버라이딩에서는 자식 클래스 객체를 통해 오버라이드된 메서드를 호출하더라도 base 키워드를 사용해 부모 클래스의 원본 구현에 접근할 수 있습니다. 반면 섀도잉에서는 자식 클래스에서 부모 클래스의 숨겨진 메서드에 직접 접근하기 어렵습니다.
3. 섀도잉 = 메서드 숨기기(Method Hiding)
섀도잉은 메서드 숨기기라고도 불립니다. 자식 클래스에서 new 키워드를 사용하면 override 키워드 없이도 부모 클래스와 동일한 이름의 메서드를 정의할 수 있으며, 이때 자식 클래스는 같은 함수의 자신만의 버전을 갖게 됩니다. 부모 클래스의 메서드가 완전히 사라지는 것이 아니라 자식 클래스 입장에서 가려지는 것입니다.
4. 서브클래스 타입별 동작 정의
오버라이딩을 활용하면 서브클래스 타입에 특화된 동작을 정의할 수 있습니다. 즉, 자식 클래스는 부모 클래스로부터 물려받은 메서드를 자신의 요구 사항에 맞게 자유롭게 구현할 수 있습니다. 이는 다형성(Polymorphism)을 실현하는 핵심 메커니즘이기도 합니다.
코드 예제로 비교하기
// 오버라이딩 예제
class Parent
{
public virtual void Show()
{
Console.WriteLine("부모 클래스 메서드");
}
}
class Child : Parent
{
public override void Show()
{
Console.WriteLine("자식 클래스 메서드");
}
}
// 섀도잉 예제
class Parent2
{
public void Display()
{
Console.WriteLine("부모 클래스 메서드");
}
}
class Child2 : Parent2
{
public new void Display()
{
Console.WriteLine("자식 클래스 메서드");
}
}
오버라이딩된 메서드는 참조 변수가 부모 타입이더라도 실제 객체가 자식 클래스라면 자식의 구현이 호출됩니다. 반면 섀도잉된 메서드는 참조 변수의 타입에 따라 호출되는 메서드가 달라집니다.
정리
간단히 요약하면, 오버라이딩은 virtual과 override 키워드를 사용해 런타임 다형성을 구현하는 방식이고, 섀도잉은 new 키워드를 사용해 부모 클래스의 메서드를 가리는 컴파일 타임 동작입니다. 상속 구조에서 일관된 다형적 동작이 필요하다면 오버라이딩을, 단순히 부모의 구현을 대체하고 싶다면 섀도잉을 선택하는 것이 바람직합니다.