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의 규칙은 다음과 같아요:
Wizard의 규칙은 다음과 같아요:
일반적으로 캐릭터는 취약하지 않아요. 하지만 Wizard는 주문을 준비하지 않았다면 취약해요.
Warrior와 Wizard 캐릭터를 다루는 여섯 개의 과제가 있어요.
Character 클래스의 ToString() 메서드를 재정의해서 "Character is a <CHARACTER_TYPE>" 형식으로 캐릭터를 설명하는 문자열을 반환하도록 해요.
var warrior = new Warrior();
warrior.ToString();
// => "Character is a Warrior"
Character.Vulnerable() 메서드가 항상 false를 반환하도록 해요.
var warrior = new Warrior();
warrior.Vulnerable();
// => false
Wizard.PrepareSpell() 메서드를 구현해서 Wizard가 미리 주문을 준비할 수 있게 해요.
var wizard = new Wizard();
wizard.PrepareSpell();
Wizard가 주문을 준비하지 않았으면 Vulnerable() 메서드가 true를 반환하고, 그렇지 않으면 false를 반환하도록 해요.
var wizard = new Wizard();
wizard.Vulnerable();
// => true
Wizard.DamagePoints() 메서드를 구현해서 입힌 피해 점수를 반환하도록 해요. 주문을 준비했으면 12점, 준비하지 않았으면 3점이에요.
var wizard = new Wizard();
var warrior = new Warrior();
wizard.PrepareSpell();
wizard.DamagePoints(warrior);
// => 12
Warrior.DamagePoints() 메서드를 구현해서 입힌 피해 점수를 반환하도록 해요. 대상이 취약하면 10점, 취약하지 않으면 6점이에요.
var warrior = new Warrior();
var wizard = new Wizard();
warrior.DamagePoints(wizard);
// => 10
Exercism에 가입하고 C# 트랙을 개념 62개연습 문제 178개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.