virtual, abstract, interface

John Jean·2025년 4월 4일

Unity

목록 보기
16/19
post-thumbnail

Virtual

다형성을 챙길 수 있는 좋은 수단

객체지향의 장점을 보여주는 형식이라고 생각함.

다형성이란 하나의 인터페이스가 여러 형태로 동작할 수 있음을 나타내는 성질인데,
virtual을 사용하면, 하나의 메서드로 다양한 출력을 나타낼 수 있다.

자식 클래스에서 재정의(Override)할 수 있는 메서드를 선언할 때 사용. 기본 구현이 존재한다.

특징

  • Abstract과는 달리 구현은 선택적.
  • 자식 클래스에서 new 또는 override 키워드 사용.(new: 기존 클래스를 숨긴다, override: 메서드를 재정의 하겠다.)
  • 자식의 클래스는 base 키워드를 통해 부모의 메서드를 호출할 수 있다.
class Monster {
    public virtual void Speak() {
        Console.WriteLine("몬스터입니다.");
    }
}

class Elf : Monster {
    public override void Speak() {
        Console.WriteLine("엘프입니다...");
    }
}

class Orc : Monster {
    public new void Speak() {
        Console.WriteLine("오크입니다...");
    }
}

class Program {
    static void Main() {
        Monster m1 = new Elf();
        Monster m2 = new Orc();

        Elf elf = new Elf();
        Orc orc = new Orc();

        m1.Speak();    // → 엘프입니다...
        m2.Speak();    // → 몬스터입니다 
        elf.Speak();   // → 엘프입니다...
        orc.Speak();   // → 오크입니다...

Monster m2 = new Orc();
m2.Speak();

이 부분을 보면 엘프라는 메시지가 나오지 않고, 부모의 메서드가 실행되는데, 이건 재정의를 해주지 않아서 그렇다.

하지만, Elf elf = new Elf(); 이런식으로 자신을 참조하면 실행시킬 수 있음.

Abstract

자식 클래스에서 반드시 구현해야 하는 메서드. 본문이 없다.
즉, Abstract이 사용되는 곳에 불완전한 구현이 있다는 것임.

Abstract클래스의 목적은 여러 파생 클래스에서 공유할 수 있는 기본 클래스의 공통적인 정의(규칙)를 제공하는 것.

특징

  • 부모 메서드는 구현부가 존재하지 않는다(밑에 코드 참고).
  • Abstract이 사용되면 파생된 클래스에서 반드시 사용해야 한다.
  • Abstract 클래스는 인스턴스화 될 수 없다. -> 완전하지 않은 코드이기 때문.
  • Abstract 메서드는 Abstract 클래스 안에서만 선언할 수 있다.
  • 파생된 클래스에선 동일한 키워드의 메서드에 override 키워드를 통해 재정의함.

이전 프로젝트 Royal Run중...

//Pickup.cs
public abstract class Pickup : MonoBehaviour
{
	protected abstract void OnPickup();
}
public class Apple : Pickup
{
    protected override void OnPickup()
    {
        levelGenerator.ChangeChunkMoveSpeed(adjustChangeMoveSpeed);
        Debug.Log("Power up.");
    }
}

Pickup 클래스에서 파생된 Apple 클래스에서 OnPickup()메서드를 재정의하는 모습.

특징에서 설명했다시피, 부모 클래스 메서드는 구현부가 없다. protected abstract void OnPickup();

형식은 virtual과 같은데, 차이점은 abstract에서는 필수로 구현해야 한다는점.

상속받는 클래스에서 override하지 않으면 에러가 난다.

모든 자식 클래스가 가져야 하되, 개별적으로 동작하게 하고자 할 때 사용하면 된다.

Interface

공통된 동작을 작성해두고, 각 클래스가 반드시 해당기능을 구현하도록 함.

C#에서 클래스는 하나의 클래스만 상속이 가능하다.

한 클래스에 여러 속성을 상속시키고 싶을 때 인터페이스를 사용하면 됨.

코드를 작성할 때 인터페이스를 상속해서, 설계도를 받는 것처럼 어떤 행동을 해야 하는지 알 수 있다.

특징

  • 다중구현 가능
public interface IWalkable { void Walk(); }
public interface ISpeakable { void Speak(); }

public class Human : MonoBehaviour, IWalkable, ISpeakable
{
    public void Walk() { }
    public void Speak() { }
}
  • 기능만 약속하고, 구현은 맡긴다.
    인터페이스상에서는 명시만 하고 필요할 때 각자 알아서 구현해야 함.

  • 다형성에 적합.
    어떤 오브젝트이든 인터페이스만 같다면 같은 방식으로 다룰 수 있다.

  • 메서드, 인덱서, 프로퍼티, 이벤트 같은 것들이 선언될 수 있음.

클래스 상속은 "is-a", 인터페이스는 "can-do" 관계.
Dalmacian is-a Dog → 클래스 상속
Player can-do IDamageable → 인터페이스

profile
크래프톤 6기 정글러

0개의 댓글