본문 바로가기
C#

C#] Virtual VS Abstract 함수 차이점

by Fastlane 2024. 2. 2.
728x90
반응형

OOP는 상속을 사용한다. 효율적이고 정돈되 코드를 위해 class의 공통 함수를 사용한다. 함수에 대해서 C#은 두가지 별도의 접근방식을 사용한다. virual 과 abstract methods이다. 둘다 polymorphism이 가능하지만, 구현과 사용방법은 상당히 다르다. 

 

Virtual vs. Abstract

대중교통 사무실을 만들어보자. 사용자는 Car, Train, Plane 중에 선택할 수 있고 이동시간과 기본요금을 알 수 있다. 

 

사용자의 옵션에 따라 대중교통 object를 초기화하는 CreateTransportMode() 함수를 갖는 TransportAgency class를 만들어보자. 

public enum TransportModeType
{
    Car,
    Plane,
    Train
}
                                                                  
internal class TransportAgency
{
    public TransportMode CreateTransportMode(TransportModeType modeType)
    {
        return modeType switch
        {
            TransportModeType.Car => new Car(60),
            TransportModeType.Train => new Train(4),
            TransportModeType.Plane => new Plane(800),
            _ => throw new ArgumentException("Invalid transport mode type."),
        };
    }
}

 

이제, GetTravelTime() abstract method와 CalculateBaseFare() virtual method를 정의하는 TransportMode abstract class를 만들자. 

internal abstract class TransportMode
{
    public abstract double GetTravelTime(double distance);

    public virtual double CalculateBaseFare(double distance)
    {
        return distance * 0.5; 
    }
}

 

교통수단에 따라 이동시간을 계산하기 위해서 GetTravelTime() 함수를 사용한다. 교통수단에 따라 이동시간이 천차만별이므로 이 함수는 abstract 이다. 이 함수에서 기본 이동시간을 제공하지 않는다. 

 

요금 계산을 하는 CalculateBaseFare()함수는 일반적으로 통용되는 기본요금을 제시하므로 virtual 함수로 만들어졌다. 자식 class는 총 요금 계산 시, 기본요금을 직접적으로 사용할지, 함수를 override해서 특정 요금 계산식을 구현할지 선택할 수 있다. 

 

자식 class에서 abstract, virtual 함수가 어떻게 사용되는지 살펴보자. 

자식 클래스

TransportMode abstract class를 상속받는 Car, Train, Plane 클래스를 작성해보자.

 

internal class Car(double averageSpeed) : TransportMode
{
    private readonly double _averageSpeed = averageSpeed;

    public override double GetTravelTime(double distance)
    {
        return distance / _averageSpeed;
    }
   
    public override double CalculateBaseFare(double distance)
    {
        return base.CalculateBaseFare(distance) + 2.5; 
    }
}

CalculateBaseFare를 override하여 계산식을 작성했다. base class로부터 기본 요금을 가져오고 연료값을 추가했다. 

또한, GetTravelTime() abstract method도 override했다. 

internal class Train(double fixedJourneyTime) : TransportMode
{
    private double _fixedJourneyTime = fixedJourneyTime;

    public override double GetTravelTime(double distance)
    {
        return _fixedJourneyTime; 
    }

    public override double CalculateBaseFare(double distance)
    {
        var baseFare = base.CalculateBaseFare(distance);

        if (distance > 500)
        {
            baseFare *= 0.9;              
        }

        return baseFare;
    }
}

긴 여행에서는 10% 할인을 제공하도록 CalculateBaseFare() 함수를 override했다. 

internal class Plane(double cruisingSpeed) : TransportMode
{
    private readonly double _cruisingSpeed = cruisingSpeed;

    public override double GetTravelTime(double distance)
    {
        return distance / _cruisingSpeed + 0.5; 
    }

    public override double CalculateBaseFare(double distance)
    {
        if (distance < 500)
        {
            return 100; 
        }
        else if (distance < 1000)
        {
            return 150; 
        }
        else
        {
            return distance * 0.2; 
        }
    }
}

base class의 기본요금을 활용하지 않고, 완전히 새로운 계산식을 구현했다. 

 

Virtual 와 Abstract Method의 차이점

  Virtual Method Abstract Method
Implementation 기본 구현 있음  구현 없음
Overriding  선택사항 non-abstract class의 의무사항
Location abstract, non-abstract class에 선언가능 abstract class에만 선언가능
Purpose 기본 기능을 override될 수 있도록 제공한다.  자식 클래스에서 abstract methods를 반드시 구현하도록 한다. 
호환되지 않는 키워드 static, abstract, private, override static, virtual
Flexibility customization하기 좋다.  일관성을 유지하기 좋다.

 

결론

virtual, abstract method의 차이점을 살펴보았다. 해당 기능을 이해하면, C#에서 OOP를 구현하도록 도와준다. 다른 기능과, 신중하게 사용하므로 클림코드와 개선된 다형성과 확장성을 얻을 수 있다. 

728x90
반응형

댓글