ポリモーフィズム
ポリモーフィズム:多態性、多様性
類似したクラスに対するメッセージの送り方を共通にする仕組み。(相手が具体的にどのクラスのインスタンスであるか意識せずにメッセージを送れる)
コード例
// 基底クラス
class Character
{
public double Hp;
public double Mp;
public double Atk;
public Character()
{
this.Hp = 100;
this.Mp = 100;
this.Atk = 100;
}
// ステータスを取得(ダミー)
public virtual string GetStatus()
{
return string.Empty;
}
}
// 派生クラス(剣士)
class Soldier : Character
{
// 剣士のステータスを取得
public override string GetStatus()
{
this.Hp = this.Hp * 1.5;
this.Mp = this.Mp * 0.5;
this.Atk = this.Atk * 2;
return $"剣士のステータスはHP:{this.Hp},MP:{this.Mp},ATK:{this.Atk}です";
}
}
// 派生クラス(魔法使い)
class Wizard : Character
{
// 魔法使いのステータスを取得
public override string GetStatus()
{
this.Hp = this.Hp * 1.3;
this.Mp = this.Mp * 2;
this.Atk = this.Atk * 0.5;
return $"魔法使いのステータスはHP:{this.Hp},MP:{this.Mp},ATK:{this.Atk}です";
}
}
class Program
{
static void Main(string[] args)
{
Character sol = new Soldier();
Character wiz = new Wizard();
PrintStatus(sol);
PrintStatus(wiz);
}
// キャラのステータス表示メソッド
static void PrintStatus(Character c)
{
Console.WriteLine(c.GetStatus());
}
}
剣士のステータスはHP:150,MP:50,ATK:200です
魔法使いのステータスはHP:130,MP:200,ATK:50です
GetStatusという同じ名前のメソッドを複数のクラスで利用できるようにして異なる挙動をさせる。
PrintStatusメソッドの引数の型はCharacterになっている。
これにより、対象が剣士や魔法使いなど何が来ても対応できる。
(異なる機能(実装)を同じ名前で呼び出せるため、保守に優れている)
抽象クラス
派生クラスにオーバーライドすることを強制することができる。
抽象メソッドを含んだクラスを抽象クラスと呼び、継承したクラスはすべての抽象メソッドをオーバーライドしなければならない。
抽象メソッドはabstract修飾子を付与して定義する。
コード例
abstract class Character
{
public double Hp;
public double Mp;
public double Atk;
public Character()
{
this.Hp = 100;
this.Mp = 100;
this.Atk = 100;
}
// 抽象メソッド
public abstract string GetStatus();
}
抽象クラスを継承したクラスからGetStatus()を削除するとエラーとなる。
抽象クラスはインスタンス化することはできない。
抽象メソッドは中身を持つことはできない。
インターフェース
抽象クラスでは多重継承ができない。実現したい機能(メソッド)を1つの抽象クラスにまとめる必要があるため、派生クラスでその機能を必要としない場合にも、機能をオーバーライドしなければいけなくなる。
インターフェースは多重継承することができる。目的に応じて異なるインターフェースをに振り分けることで、派生クラス側も必要に応じてインターフェースを選択できるようになる。
インターフェースはinterface命令を利用する。
コード例
// インターフェース
interface ICharacter
{
string GetStatus();
}
class Archer : ICharacter
{
public double Hp;
public double Mp;
public double Atk;
public string GetStatus()
{
this.Hp = this.Hp * 1.1;
this.Mp = this.Mp * 1.7;
this.Atk = this.Atk * 1.7;
return $"弓使いのステータスはHP:{this.Hp},MP:{this.Mp},ATK:{this.Atk}です";
}
}
インターフェース名は大文字Iで始めること。
インターフェース配下の抽象メンバーにabstaractは不要。
抽象クラスとインターフェースのどちらを利用するか迷ったら、インターフェースを優先して利用する。
参考した本
独習C#
おわり。