C# 문법 3주차 - 다형성

Amberjack·2024년 1월 2일
0

C# 문법

목록 보기
18/44

📚 다형성

같은 타입이지만 다양한 동작을 수행할 수 있는 능력!

🖥️ 가상(Virtual) 메서드

  • 부모 클래스에서 정의되고 자식 클래스에서 재정의할 수 있는 메서드
  • virtual 키워드로 선언, 자식 클래스에서 필요에 의해 재정의 가능
  • 자식 클래스에서 부모 클래스의 메서드를 변경, 확장 가능!

▪️ 가상 메서드를 사용하는 이유

virtual이 선언되어 있을 때, 참조 형태와 실 형태가 다를 경우, 재정의된 override가 실행된다!!

단순히 메서드를 재정의하여 부모의 메서드를 숨겨서 코드를 짠다고 가정해보자.
ex) 아래와 같이 Unit을 상속받는 Marine과 Zergling이 있다.

public class Unit
{
    public void Move()
    {
        Console.WriteLine("두발로 걷기");
    }

    public void Attack()
    {
        Console.WriteLine("Unit 공격");
    }
}

public class Marine : Unit
{

}

public class Zergling : Unit
{
	public void Move()
{
    Console.WriteLine("네발로 걷기");
}
}

그리고 메인에서 아래와 같은 코드를 실행한다고 해보자.

해당 코드를 실행시키면 Marine과 Zergling을 개별적으로 선언했을 때는 문제가 발생하지 않는다.

하지만 아래의 Unit으로 합쳐서 Move를 실행할 경우(부모 클래스로 통합하여 관리할 경우), 의도했던 것과 다른 결과가 나온다.

unit.Move()를 호출하니 Zergling 또한 두발로 걷기가 출력되는 모습.
이는 부모 클래스의 Unit에서 move를 호출해서 자식 클래스의 네발로 걷기가 호출되지 않았기 때문이다.

public class Unit
{
    public virtual void Move()
    {
        Console.WriteLine("두발로 걷기");
    }

    public void Attack()
    {
        Console.WriteLine("Unit 공격");
    }
}

public class Marine : Unit
{

}

public class Zergling : Unit
{
    public override void Move()
    {
        Console.WriteLine("네발로 걷기");
    }
}

이번엔 위와 같이 코드를 수정해보자.

이 때, virtual은 '내가 Unit의 Move이기는 하지만 참조형이니 실 형태가 다를 수 있다. 실 형태(Marine, Zergling)에 가서 확인해보아라' 라는 의미를 지닌다.

때문에 컴파일러가 virtual을 확인하고 자식 클래스로 와서 상속받은 Move를 확인할 때, 'override'가 선언되어 있으면 해당 실형태로 변환한다.

위의 코드에서 Unit은 참조형, Marine과 Zergling이 실 형태이다. unit.Move()는 virtual로 선언되어 있기 때문에 각자 실 형태를 확인하게 된다. 이 때, Marine은 Move()를 재정의하지 않았기 때문에 그대로 출력되지만, Zergling의 경우는 다르기 때문에 재정의된 Move()가 출력되게 된다.

🤓 추상(Abstract) 클래스와 메서드

  • 추상 클래스는 직접적으로 인스턴스를 생성할 수 없다.
  • 주로 상속을 위한 베이스 클래스로 사용된다.
  • abstract 키워드를 사용하여 선언, 추상 메서드를 포함할 수 있다.
  • 추상 메서드는 구현부가 없는 메서드로, 자식 클래스에서 반드시 구현되어야 한다.
abstract class Shape
{
    public abstract void Draw();
}

class Circle : Shape
{
    public override void Draw()
    {
        Console.WriteLine("Drawing a circle");
    }
}

class Square : Shape
{
    public override void Draw()
    {
        Console.WriteLine("Drawing a square");
    }
}

class Triangle : Shape
{
    public override void Draw()
    {
        Console.WriteLine("Drawing a triangle");
    }
}

❗ 오버라이딩과 오버로딩

▪️ 오버라이딩(Overriding)

  • 부모 클래스에서 이미 정의된 메서드를 자식 클래스에서 재정의하는 것.
  • 상속 관계에 있는 클래스 간에 발생, 메서드의 이름, 매개변수 및 반환타입이 동일해야 함
  • 오버라이딩을 통해 자식 클래스는 메서드를 재정의하여 자신에게 맞는 동작을 구현할 수 있다.

▪️ 오버로딩(Overloading)

  • 동일한 메서드 이름을 가지고 있지만, 매개변수의 개수, 타입 또는 순서가 다른 여러 개의 메서드를 정의하는 것.
  • 오버로딩을 통해 동일한 이름을 가진 메서드를 다양한 매개변수 조합으로 호출할 수 있다.

0개의 댓글