C#에서 virtual(가상) 키워드는 메서드, 속성(property), 인덱서, 이벤트를 수정하는 데 사용됩니다. 기반 클래스(부모 클래스)에 정의된 함수를 상속받는 파생 클래스에서 각자의 방식으로 다시 구현하고 싶을 때 가상 함수를 활용합니다.
가상 함수는 상속 관계에 있는 클래스마다 서로 다르게 구현될 수 있으며, 어떤 함수가 호출될지는 컴파일 시점이 아닌 런타임에 결정됩니다. 이것이 바로 C# 다형성(Polymorphism)의 핵심 원리입니다.
가상 함수 선언 방법
메서드 앞에 virtual 키워드를 붙이면 해당 메서드는 파생 클래스에서 재정의(override)할 수 있는 가상 함수가 됩니다.
public virtual int area() { }virtual과 override의 관계
- virtual: 기반 클래스에서 "이 메서드는 자식 클래스에서 재정의할 수 있다"고 선언하는 키워드입니다.
- override: 파생 클래스에서 부모의 가상 메서드를 새롭게 구현할 때 사용합니다.
- 동적 바인딩: 실행 시점에 객체의 실제 타입을 확인하여 알맞은 메서드가 호출됩니다.
C# 가상 함수 예제
Shape(도형)라는 기반 클래스를 만들고, 이를 상속받는 Rectangle(사각형)과 Triangle(삼각형) 클래스에서 각각 area() 메서드를 다르게 구현한 예제입니다.
using System;
namespace PolymorphismApplication {
class Shape {
protected int width, height;
public Shape(int a = 0, int b = 0) {
width = a;
height = b;
}
public virtual int area() {
Console.WriteLine("부모 클래스 area() 호출 :");
return 0;
}
}
class Rectangle : Shape {
public Rectangle(int a = 0, int b = 0) : base(a, b) {
}
public override int area() {
Console.WriteLine("Rectangle(사각형) 클래스 area()");
return (width * height);
}
}
class Triangle : Shape {
public Triangle(int a = 0, int b = 0) : base(a, b) {
}
public override int area() {
Console.WriteLine("Triangle(삼각형) 클래스 area()");
return (width * height / 2);
}
}
class Caller {
public void CallArea(Shape sh) {
int a;
a = sh.area();
Console.WriteLine("면적: {0}", a);
}
}
class Tester {
static void Main(string[] args) {
Caller c = new Caller();
Rectangle r = new Rectangle(10, 7);
Triangle t = new Triangle(10, 5);
c.CallArea(r);
c.CallArea(t);
Console.ReadKey();
}
}
}실행 결과
Rectangle(사각형) 클래스 area() 면적: 70 Triangle(삼각형) 클래스 area() 면적: 25
예제 코드 분석
코드가 동작하는 흐름을 단계별로 살펴보겠습니다.
- 기반 클래스 Shape: width와 height 필드를 protected로 선언해 파생 클래스에서 접근할 수 있게 하고, area() 메서드를 virtual로 선언합니다.
- 파생 클래스 Rectangle, Triangle: 각각 override 키워드로 area()를 재정의합니다. 사각형은 가로×세로, 삼각형은 가로×세로÷2로 면적을 계산합니다.
- Caller 클래스: CallArea() 메서드는 매개변수로 Shape 타입을 받으므로, Rectangle 객체든 Triangle 객체든 모두 전달할 수 있습니다.
- 런타임 결정: CallArea(r) 호출 시에는 Rectangle의 area()가, CallArea(t) 호출 시에는 Triangle의 area()가 실행됩니다. 컴파일러가 아니라 런타임에 객체의 실제 타입을 보고 호출할 메서드를 결정하기 때문입니다.
정리
C#의 가상 함수는 객체 지향 프로그래밍의 다형성을 구현하는 핵심 도구입니다. virtual로 선언된 메서드는 파생 클래스에서 override로 재정의할 수 있으며, 런타임에 객체의 실제 타입에 따라 적절한 메서드가 호출됩니다. 이를 통해 하나의 인터페이스로 다양한 동작을 처리하는 유연하고 확장 가능한 코드를 작성할 수 있습니다.