RPGでボスがプレイヤーのパーティに攻撃するようなイメージでインターフェースを実装
インターフェースの学習で考えられるコードは次のようになります
「Warrior」と「Wizard」という2つのキャラクターを含むリストがあり、「Boss」というキャラクターがそれらを攻撃するプログラムです。
List<IDamageable> characters = new List<IDamageable>()
{
new Warrior(),
new Wizard()
};
Boss boss = new Boss();
foreach (IDamageable character in characters)
{
boss.Attack(character);
}
interface IDamageable
{
void TakeDamage(int damage);
}
class Warrior : IDamageable
{
public void TakeDamage(int damage)
{
Console.WriteLine($"戦士は{damage}のダメージを受けた");
}
}
class Wizard : IDamageable
{
public void TakeDamage(int damage)
{
Console.WriteLine($"魔導士は{damage}のダメージを受けた");
}
}
class Boss
{
public void Attack(IDamageable target)
{
target.TakeDamage(10);
}
}
このC#コードは、「Warrior」と「Wizard」という2つのキャラクターを含むリストがあり、「Boss」というキャラクターがそれらを攻撃するプログラムです。
まず、IDamageable
というインターフェイスが定義されています。このインターフェイスは、TakeDamage
メソッドを定義しています。このメソッドは、キャラクターがダメージを受けたときに呼び出されます。
次に、Warrior
とWizard
という2つのクラスが定義されています。この2つのクラスは、IDamageable
インターフェイスを実装しています。このため、各クラス内でTakeDamage
メソッドが実装されています。
次に、Boss
クラスが定義されています。このクラスは、Attack
メソッドを定義しています。このメソッドは、引数として渡されたIDamageable
インターフェイスを実装したキャラクターに10のダメージを与えます。
最後に、Main
メソッドが定義されています。このメソッドでは、「Warrior」と「Wizard」という2つのキャラクターを含むリストが作成され、「Boss」がこのリスト内のキャラクターを1つずつ攻撃する処理が行われます。
インターフェースを使うのメリット
- 多様性: インターフェースを実装した複数のクラスが同じように扱われることができます。例えば、このコードでは
Warrior
とWizard
は、IDamageable
インターフェイスを実装しています。このため、同じように攻撃を受けることができます。 - 再利用性: インターフェースを実装したクラスは、他のクラスやメソッドから再利用することができます。例えば、このコードでは
Boss
クラスは、IDamageable
インターフェースを実装したキャラクターを攻撃することができます。 - 抽象性: インターフェースは具体的な実装を持たないため、抽象的な概念を表現することができます。例えば、このコードでは
IDamageable
インターフェイスは、「ダメージを受けることができるもの」という概念を表現しています。 - 型安全性: インターフェースを使うことで、型安全性を向上させることができます。例えば、このコードでは
Attack
メソッドは、引数としてIDamageable
インターフェイスを実装したものだけを受け付けます。このため、他のクラスや型を誤って渡すことができなくなります。
抽象クラスを定義して、Helthメンバーを追加するように変更
abstract class Character
{
public int Health { get; set; }
}
class Warrior : Character, IDamageable
{
public void TakeDamage(int damageAmount)
{
Health -= damageAmount;
}
}
class Wizard : Character, IDamageable
{
public void TakeDamage(int damageAmount)
{
Health -= damageAmount;
}
}
class Boss
{
public void Attack(IDamageable target)
{
target.TakeDamage(10);
}
}
class Program
{
static void Main(string[] args)
{
var characters = new List<IDamageable>
{
new Warrior { Health = 100 },
new Wizard { Health = 80 }
};
var boss = new Boss();
foreach (var character in characters)
{
boss.Attack(character);
Console.WriteLine($"{character.GetType().Name} Health: {character.Health}");
}
}
}
このコードは、「Warrior」と「Wizard」という2つのキャラクターを含むリストと、「Boss」というキャラクターがそれらを攻撃するプログラムです。
まず、Character
という抽象クラスがあります。このクラスには、キャラクターが持つHealth
プロパティが定義されています。
次に、Warrior
とWizard
クラスがあります。これらのクラスは、Character
クラスを継承しています。また、IDamageable
というインターフェイスを実装しています。このインターフェイスは、キャラクターが攻撃を受けるときに使用するTakeDamage
メソッドを定義しています。
次に、Boss
クラスがあります。このクラスは、攻撃するキャラクターを引数として受け取り、そのキャラクターに対してTakeDamage
メソッドを呼び出すことで攻撃を行います。
最後に、Program
クラスがあります。このクラスは、Main
メソッドを持っており、アプリケーションのエントリポイントとなります。Main
メソッドでは、「Warrior」と「Wizard」という2つのキャラクターを含むリストを作成し、「Boss」によって攻撃を行います。攻撃後に、各キャラクターのHealth
プロパティをコンソールに表示します。
抽象クラスの継承とインターフェースの実装のメリット
- インターフェースを使用することで、各キャラクターが共通の振る舞いを実装することができます。例えば、「Warrior」と「Wizard」が「Boss」の攻撃を受けることができるという振る舞いは、同じ
TakeDamage
メソッドを使用することで実現されます。このように、各キャラクターの振る舞いをまとめることで、コードの保守性が向上します。 - 抽象クラスを使用することで、各キャラクターが共通のプロパティを持つことができます。例えば、「Warrior」と「Wizard」は共通の
Health
プロパティを持つことができます。このように、各キャラクターが共通のプロパティを持つことで、コードの保守性が向上します。 - インターフェースと抽象クラスを使用することで、今後の要件変更にも柔軟に対応することができます。例えば、新しいキャラクターを追加する場合も、インターフェースを実装して振る舞いを定義することができます。また、新しいプロパティを追加する場合も、抽象クラスに追加することができます。このように、インターフェースと抽象クラスを使用することで、今後の要件変更にも柔軟に対応することができます。
抽象クラスの継承とインターフェースの実装のデメリット
このクラスのデメリットは以下のとおりです。
- 複雑性の増加: インターフェースと抽象クラスを使用することで、コードが複雑になる可能性があります。特に、初めてインターフェースや抽象クラスを使用する開発者にとっては理解するのが難しいかもしれません。
- パフォーマンス低下: インターフェースと抽象クラスを使用することで、パフォーマンスが低下する可能性があります。これは、インターフェースと抽象クラスを使用すると呼び出すメソッドが一層深くなり、呼び出すたびにオーバーヘッドが生じるからです。
- 制約の増加: インターフェースや抽象クラスを使用することで、開発者が実装する上での制約が増加する可能性があります。例えば、インターフェースを実装する際には必ず全てのメソッドを実装する必要があります。また、抽象クラスを継承する際には、継承元のクラスの振る舞いを適切に実装する必要があります。
ディスカッション
コメント一覧
まだ、コメントがありません