[C#] virtual function, abstract class, interface

강한·2025년 3월 11일

CSharp

목록 보기
1/1

virtual function

가상 함수(virtual function)는 파생 클래스에서 재정의 할 것으로 기대하는 멤버 함수를 의미한다. 파생 클래스에서 필요에 따라서 재정의(override) 할 수 있지만 필수적으로 재정의 할 필요는 없다. virtual 한정자를 사용한 클래스는 완벽한 기능을 제공할 수 있다. (구현부를 제공한다)

public class Animal
{   
	public virtual void Speak()   
	{        
		Console.WriteLine("Nothing!");   
	}
} 
public class Dog : Animal
{    
	public override void Speak()    
	{        
		Console.WriteLine("멍멍!");    
	}
} 

Dog temp = new Dog();
temp.Speak();//멍멍!

사용 예시

  • 기본 동작을 제공하면서도, 필요할 때 자식 클래스에서 변경할 수 있도록 하고 싶을 때
  • 자식 클래스가 부모 클래스의 메서드를 선택적으로 변경할 수 있도록 할 때
  • 공격, 이동, 점프 같은 기본 기능을 제공하지만, 캐릭터별로 다르게 동작해야 하는 경우

abstract function

파생 클래스에서 반드시 재정의해야 하는 멤버 함수를 의미한다. 이러한 추상 함수는 함수 본체(구현부)가 없고, 메서드 시그니처만 존재한다. 따라서 파생 클래스에서 재정의하지 않으면 사용할 수 없다.

  • C++에서는 pure virtual function(순수 가상 함수)가 이 역할을 대신한다.
  • C#에서는 추상함수가 존재할 때, 반드시 클래스에 absract키워드를 추가해야 한다.

abstract class

하나 이상의 추상 함수(순수 가상 함수)를 포함하는 클래스를 추상클래스라고 한다. 즉, 반드시 사용되어야 하는 멤버함수를 추상클래스에 추상 함수로 선언해 놓으면, 이 클래스로부터 파생된 모든 클래스에서는 이 추상 함수를 반드시 재정의 해야한다.

  • 추상 클래스는 추상 함수를 포함하고 있으므로, 인스턴스를 생성할 수 없다.
  • 생성자를 선언할 수 있다.
  • 추상클래스가 추상클래스를 상속받거나 인터페이스를 구현할 때, 추상 메서드를 반드시 구현할 필요는 없다.
  • 필드와 일반메서드를 함께 둘 수 있다.
  • 보통 추상클래스는 하나 이상의 추상메서드를 포함하는 것이 일반적이지만 개발자가 추상화를 위해 추상클래스를 명시하고 추상메서드를 포함 하지 않을 수도 있다.
public abstract class Animal
{    
	public abstract void Speak();    
	
}
public class Dog : Animal
{
	public override void Speak()
	{
		Console.WriteLine("멍멍!");
	}
}
Dog temp = new Dog();
Animal temp1 = new Animal(); // 컴파일에러
temp.Speak();//멍멍!

사용 예시

  • 공통적인 코드(메서드, 필드)를 재사용하면서, 일부 기능을 자식 클래스에서 강제 구현해야 할 때
  • 게임 내 모든 캐릭터가 공유하는 기능(체력, 공격, 점프 등)을 제공하지만, 일부 기능(이동 방식 등)은 개별적으로 구현해야 할 때
  • 중복 코드를 최소화하면서도, 캐릭터별로 커스터마이징할 수 있도록 만들고 싶을 때

virtual 과 abstract

  • 공통 기능을 제공하면서 필요하면 변경할 수 있도록 하고 싶다. → virtual function
  • 모든 자식 클래스가 반드시 구현해야 하는 기능이다. → abstract method

Interface

interface는 멤버 변수를 가지지 못하고 메소드, 이벤트, 인덱서, 프로퍼티만을 가질 수 있다. 인터페이스는 보통 여러 클래스에 공통적인 기능을 추가하기 위해 사용된다. 다중상속이 불가능한 C#에서 다중 구현이 가능하게 해준다.

public interface ISpeakable
{
	void Speak();
}
public interface IEatable
{
	void eat();
}

public interface IHitable
{
	void hit();
}

public class Speaker : ISpeakable
{
    public void Speak()
    {
        Console.WriteLine("노래재생");
    }
}

public class Dog : ISpeakable, IEatable, IHitable
{
    public void Speak()
    {
        Console.WriteLine("멍멍!");
    }
    public void Eat()
    {
        Console.WriteLine("호로록");
    }
    public void Hit()
    {
        Console.WriteLine("깨물기");
    }
}

ISpeakable dog = new Dog();
dog.Speak(); // 출력: 멍멍!
  • 추상 메서드만 가질 수 있다 (absract키워드를 포함하진 않다)
  • 인스턴스 필드(각 객체들이 가지는 별개의 변수)를 둘 수 없다
  • 인터페이스에 선언된 멤버는 기본적으로 public으로 간주
  • 생성자를 선언할 수 없다.
  • 추상 클래스는 단일 상속만 가능하지만, 인터페이스는 다중 구현이 가능하다.
  • C# 8.0 이후로, defaul interface method(기본구현메서드)를 제공하지만 인스턴스 필드는 여전히 사용할 수 없다.

사용 예시

  • 서로 다른 클래스들이 특정 기능(예: 인터랙션)을 강제적으로 가지도록 만들고 싶을 때
  • 다중 상속이 필요할 때 (C#에서는 클래스 다중 상속 불가하지만, 인터페이스는 다중 구현 가능)
  • 공통된 기능이지만, 구현 방식이 전혀 다른 오브젝트들이 있을 때 (예: NPC와 문이 같은 (interact) 기능을 가짐)
profile
의지 강한 게임개발자

0개의 댓글