C#에서는 상속 관계에 있는 클래스 간에 부모 클래스의 메서드를 자식 클래스가 다르게 동작하도록 만들 수 있습니다. 이때 사용되는 대표적인 방법이 메서드 재정의(Overriding)와 메서드 숨기기(Method Hiding, Shadowing)입니다. 두 기능은 비슷해 보이지만 동작 방식과 용도가 완전히 다르므로, 그 차이를 정확히 이해하는 것이 중요합니다.
메서드 재정의(Overriding)란?
재정의(Overriding)는 자식 클래스가 부모 클래스로부터 상속받은 가상(virtual) 또는 추상(abstract) 메서드를 override 키워드를 사용하여 자신의 요구 사항에 맞게 다시 구현하는 것을 말합니다.
재정의된 메서드는 다형성(Polymorphism)을 지원합니다. 즉, 부모 클래스 타입의 변수로 자식 객체를 참조하더라도 실제 객체 타입에 맞는 자식 클래스의 메서드가 호출됩니다.
다음은 추상 클래스를 활용한 재정의 예제입니다.
예제 코드
using System;
namespace PolymorphismApplication {
abstract class Shape {
public abstract int area();
}
class Rectangle : Shape {
private int length;
private int width;
public Rectangle(int a = 0, int b = 0) {
length = a;
width = b;
}
public override int area() {
Console.WriteLine("Rectangle class area :");
return (width * length);
}
}
class RectangleTester {
static void Main(string[] args) {
Rectangle r = new Rectangle(10, 7);
double a = r.area();
Console.WriteLine("Area: {0}", a);
Console.ReadKey();
}
}
}
실행 결과:
Rectangle class area : Area: 70
위 예제에서 Shape 추상 클래스의 area() 메서드를 Rectangle 클래스가 override 키워드로 재정의하여, 사각형의 넓이를 계산하는 고유한 동작을 구현했습니다.
메서드 숨기기(Method Hiding, Shadowing)란?
메서드 숨기기는 흔히 섀도잉(Shadowing)이라고도 불립니다. 숨기기에서는 자식 클래스가 부모 클래스와 동일한 이름의 메서드를 override 키워드 없이 자체 버전으로 구현합니다.
숨기기를 수행하려면 new 키워드를 사용합니다. 중요한 차이점은, 숨겨진 메서드는 참조 변수의 타입을 기준으로 호출된다는 점입니다. 따라서 부모 클래스 타입 변수로 호출하면 부모의 메서드가 실행되고, 자식 클래스 타입 변수로 호출하면 자식의 메서드가 실행됩니다.
예제 코드
using System;
using System.Collections.Generic;
class Demo {
public class Parent {
public string Display() {
return "Parent Class!";
}
}
public class Child : Parent {
public new string Display() {
return "Child Class!";
}
}
static void Main(String[] args) {
Child child = new Child();
Console.WriteLine(child.Display());
}
}
실행 결과:
Child Class!
위 예제에서 Child 클래스는 new 키워드를 사용해 부모의 Display() 메서드를 숨기고 자신만의 버전을 정의했습니다. 자식 타입 변수로 호출했기 때문에 "Child Class!"가 출력됩니다.
두 방식의 핵심 차이점 요약
- 키워드: 재정의는
override, 숨기기는new키워드를 사용합니다. - 사전 조건: 재정의는 부모 메서드가
virtual,abstract또는override여야 하며, 숨기기에는 이러한 제약이 없습니다. - 다형성: 재정의된 메서드는 객체의 실제 타입을 기준으로 호출되어 다형성을 지원하지만, 숨겨진 메서드는 참조 변수의 컴파일 타임 타입을 기준으로 호출됩니다.
- 용도: 부모의 동작을 확장·변경하려면 재정의를, 부모 메서드와 독립적으로 같은 이름의 새 메서드가 필요할 때는 숨기기를 사용하는 것이 적합합니다.
결론적으로, 상속 구조에서 일관된 다형성 동작이 필요하다면 override를 통한 재정의를 사용하고, 단순히 부모의 메서드를 감추고 새로운 구현을 제공하고자 할 때는 new 키워드를 통한 메서드 숨기기를 활용하면 됩니다.