트랙
/
C#
C#
/
연습 문제
/
마법사와 전사
마법사와 전사

마법사와 전사

학습 연습 문제

소개

상속

C#에서는 상속 을 사용해 클래스 계층을 정의할 수 있어요. 상속을 이용하면 파생 클래스(Car)가 부모 클래스(Vehicle)의 동작과 데이터를 물려받을 수 있어요. 부모를 지정하지 않으면 클래스는 object 클래스를 상속받아요.

부모 클래스는 세 가지 방식으로 파생 클래스에 기능을 제공할 수 있어요:

  • 일반 메서드를 정의해요.
  • virtual 메서드를 정의해요. 일반 메서드와 비슷하지만 파생 클래스가 바꿀 수 있는 메서드예요.
  • abstract 메서드를 정의해요. 구현이 없는 메서드로, 파생 클래스가 반드시 구현해야 해요. abstract 메서드가 있는 클래스는 클래스 자체도 abstract로 표시해야 해요. 추상 클래스는 인스턴스로 만들 수 없어요.

protected 접근 제한자는 부모 클래스의 멤버를 파생 클래스에서 접근할 수 있게 해 주지만, 다른 클래스에서는 접근을 막아요.

파생 클래스는 base 키워드를 통해 부모 클래스의 멤버에 접근할 수 있어요.

// Inherits from the 'object' class
abstract class Vehicle
{
    // Can be overridden
    public virtual void Drive()
    {
    }

    // Must be overridden
    protected abstract int Speed();
}

class Car : Vehicle
{
    public override void Drive()
    {
        // Override virtual method

        // Call parent implementation
        base.Drive();
    }

    protected override int Speed()
    {
        // Implement abstract method
    }
}

파생 클래스의 생성자는 자신의 생성자 로직을 실행하기 전에 부모의 생성자를 자동으로 호출해요. base 키워드를 사용하면 부모 클래스의 생성자에 인자를 전달할 수 있어요:

abstract class Vehicle
{
    protected Vehicle(int wheels)
    {
        Console.WriteLine("Called first");
    }
}

class Car : Vehicle
{
    public Car() : base(4)
    {
        Console.WriteLine("Called second");
    }
}

하나의 기본 클래스에서 두 개 이상의 클래스가 파생되면, 그 두 개(또는 그 이상)의 클래스는 흔히 기본 클래스 메서드를 서로 다른 버전으로 구현해요. 이를 다형성이라고 하는데, 아주 중요한 원리예요. 예를 들어, 위 예제를 변형한 아래 코드는 Vehicle을 사용하는 코드가 어떤 종류의 탈것이 인스턴스화되었는지에 따라 동작을 바꿀 수 있는지 보여줘요.

abstract class Vehicle
{
   public abstract string GetDescription();
}

class Car : Vehicle
{
   public Car()
   {
   }

   public override string GetDescription()
   {
      return "Runabout";
   }
}

class Rig : Vehicle
{
   public Rig()
   {
   }

   public override string GetDescription()
   {
      return "Big Rig";
   }
}

Vehicle v1 = new Car();
Vehicle v2 = new Rig();

v1.GetDescription();
// => Runabout
v2.GetDescription();
// => Big Rig

지침

이 연습 문제에서는 "Wizard and Warriors"라는 롤플레잉 게임을 플레이해요. 이 게임에서는 Wizard 또는 Warrior로 플레이할 수 있어요.

Warrior와 Wizard가 입히는 피해 점수를 정하는 규칙은 서로 달라요.

Warrior의 규칙은 다음과 같아요:

  • 공격 대상이 취약하지 않으면 6점의 피해를 입혀요
  • 공격 대상이 취약하면 10점의 피해를 입혀요

Wizard의 규칙은 다음과 같아요:

  • Wizard가 미리 주문을 준비했으면 12점의 피해를 입혀요
  • Wizard가 주문을 준비하지 않았으면 3점의 피해를 입혀요

일반적으로 캐릭터는 취약하지 않아요. 하지만 Wizard는 주문을 준비하지 않았다면 취약해요.

Warrior와 Wizard 캐릭터를 다루는 여섯 개의 과제가 있어요.

1. 캐릭터 설명하기

Character 클래스의 ToString() 메서드를 재정의해서 "Character is a <CHARACTER_TYPE>" 형식으로 캐릭터를 설명하는 문자열을 반환하도록 해요.

var warrior = new Warrior();
warrior.ToString();
// => "Character is a Warrior"

2. 캐릭터가 기본적으로 취약하지 않게 만들기

Character.Vulnerable() 메서드가 항상 false를 반환하도록 해요.

var warrior = new Warrior();
warrior.Vulnerable();
// => false

3. Wizard가 주문을 준비할 수 있게 하기

Wizard.PrepareSpell() 메서드를 구현해서 Wizard가 미리 주문을 준비할 수 있게 해요.

var wizard = new Wizard();
wizard.PrepareSpell();

4. 주문을 준비하지 않았을 때 Wizard가 취약하게 만들기

Wizard가 주문을 준비하지 않았으면 Vulnerable() 메서드가 true를 반환하고, 그렇지 않으면 false를 반환하도록 해요.

var wizard = new Wizard();
wizard.Vulnerable();
// => true

5. Wizard의 피해 점수 계산하기

Wizard.DamagePoints() 메서드를 구현해서 입힌 피해 점수를 반환하도록 해요. 주문을 준비했으면 12점, 준비하지 않았으면 3점이에요.

var wizard = new Wizard();
var warrior = new Warrior();

wizard.PrepareSpell();
wizard.DamagePoints(warrior);
// => 12

6. Warrior의 피해 점수 계산하기

Warrior.DamagePoints() 메서드를 구현해서 입힌 피해 점수를 반환하도록 해요. 대상이 취약하면 10점, 취약하지 않으면 6점이에요.

var warrior = new Warrior();
var wizard = new Wizard();

warrior.DamagePoints(wizard);
// => 10
GitHub에서 편집 링크가 새 창이나 탭에서 열려요
C# Exercism

마법사와 전사 문제를 시작해 볼 준비가 됐나요?

Exercism에 가입하고 C# 트랙을 개념 62개연습 문제 178개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.