Computer >> 컴퓨터 >  >> 프로그래밍 >> C#

C# 가상 함수(virtual)란? 개념부터 예제까지 한 번에 이해하기

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

예제 코드 분석

코드가 동작하는 흐름을 단계별로 살펴보겠습니다.

  1. 기반 클래스 Shape: width와 height 필드를 protected로 선언해 파생 클래스에서 접근할 수 있게 하고, area() 메서드를 virtual로 선언합니다.
  2. 파생 클래스 Rectangle, Triangle: 각각 override 키워드로 area()를 재정의합니다. 사각형은 가로×세로, 삼각형은 가로×세로÷2로 면적을 계산합니다.
  3. Caller 클래스: CallArea() 메서드는 매개변수로 Shape 타입을 받으므로, Rectangle 객체든 Triangle 객체든 모두 전달할 수 있습니다.
  4. 런타임 결정: CallArea(r) 호출 시에는 Rectangle의 area()가, CallArea(t) 호출 시에는 Triangle의 area()가 실행됩니다. 컴파일러가 아니라 런타임에 객체의 실제 타입을 보고 호출할 메서드를 결정하기 때문입니다.

정리

C#의 가상 함수는 객체 지향 프로그래밍의 다형성을 구현하는 핵심 도구입니다. virtual로 선언된 메서드는 파생 클래스에서 override로 재정의할 수 있으며, 런타임에 객체의 실제 타입에 따라 적절한 메서드가 호출됩니다. 이를 통해 하나의 인터페이스로 다양한 동작을 처리하는 유연하고 확장 가능한 코드를 작성할 수 있습니다.