ポリモーフィズムのサンプル(将棋サンプルの一部)

基本サンプル

Piece fu = new Fu();

class Piece
{
}

class Fu : Piece
{
}

このコードは、JavaやC#などのオブジェクト指向プログラミング言語で書かれた、クラスと継承の概念を使ったサンプルコードです。

このコードは、Piece というクラスを定義し、それを継承した Fu というクラスを定義しています。Piece クラスは何も機能を持っておらず、単に Piece クラスを継承したクラスが作成できるようにするためのものです。

次に、Fu クラスのオブジェクトを作成しています。Fu クラスは Piece クラスを継承しているため、Fu クラスのオブジェクトは Piece クラスのオブジェクトとして扱うことができます。このように、継承関係にあるクラスのオブジェクトは、親クラスの型として扱うことができます。

具体的には、Piece Fu = new Fu(); の文では、Fu クラスのオブジェクトを作成し、そのオブジェクトを Piece 型の変数 Fu に代入しています。これにより、Fu 変数は Piece 型として扱われ、Fu クラスで定義されたメソッドやプロパティにはアクセスできませんが、Piece クラスで定義されたメソッドやプロパティにはアクセスできます。

このように、継承を使うことで、共通の機能を持つクラスを定義し、それを継承するクラスで特化した機能を実装することができます。また、継承関係にあるクラスのオブジェクトを、親クラスの型として扱うことで、柔軟なプログラミングを実現することができます。

ポリモーフィズム

基本

var fu = new Fu();

abstract class Piece
{
    abstract public bool CanMoveTo(int x, int y);
}

class Fu : Piece
{
    public override bool CanMoveTo(int x, int y)
    {
        return true;
    }
}

このコードは、将棋の駒を表現するオブジェクト指向プログラミングの基本的な実装例です。

変数 fu は、将棋の「歩」を表すオブジェクトを作成するために使用されます。

Piece クラスは、将棋の駒を表す抽象クラスです。このクラスには、駒が指定された座標に移動できるかどうかを判断する CanMoveTo メソッドが含まれます。このメソッドは、派生クラスで実装される必要があります。

Fu クラスは、Piece クラスから派生したクラスであり、「歩」駒を表します。Fu クラスは、CanMoveTo メソッドをオーバーライドして、駒がどの位置にでも移動できるようにしています。この実装は、将棋の「歩」駒が、前方に1マス進むことができるという基本的な動作を表しています。

このコードは、将棋の駒を表現するオブジェクト指向プログラミングの基本的な構成要素を示しています。将来的には、他の将棋の駒を表すクラスを追加し、さまざまな駒の動きを正確に表現するように拡張することができます。

駒ごとの移動チェック

Piece fu = new Fu(2, 7);
fu.CanMoveTo(2, 6);

abstract class Piece
{
    // 駒の位置を表すフィールド
    protected int x;
    protected int y;

    // コンストラクタで駒の位置を指定
    public Piece(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    abstract public bool CanMoveTo(int x, int y);
}

class Fu : Piece
{
    public Fu(int x, int y) : base(x, y)
    {
    }
    // 歩は前に一歩だけ進むことができる
    public override bool CanMoveTo(int x, int y)
    {
        return x == this.x && y == this.y - 1;
    }
}

このコードは、将棋の駒を表現するためのクラスを定義しています。

まず、Pieceという抽象クラスが定義されています。このクラスは、駒の位置を表すxとyというフィールドと、コンストラクタを持っています。コンストラクタでは、駒の初期位置を指定します。

次に、Fuというクラスが定義されています。Fuクラスは、Pieceクラスを継承しています。Fuクラスは、駒の種類が「歩」であることを表しています。Fuクラスのコンストラクタでは、駒の初期位置を指定することができます。Fuクラスは、Pieceクラスの抽象メソッドであるCanMoveToをオーバーライドしています。CanMoveToメソッドは、指定した座標に移動可能かどうかを判断します。

FuクラスのCanMoveToメソッドの実装では、指定した座標が現在の座標よりも1つ上の行であるかどうかを判定しています。つまり、Fuクラスのインスタンスは、現在の位置から前に1つだけ進むことができます。

例えば、以下のコードを実行すると、Fuクラスのインスタンスを作成し、そのインスタンスが指定した座標に移動できるかどうかを判断します。

Piece fu = new Fu(2, 7);
fu.CanMoveTo(2, 6);

駒の香を追加

class Kyou : Piece
{
    public Kyou(int x, int y) : base(x, y)
    {
    }

    // 香車は、前に何歩でも進むことができる
    public override bool CanMoveTo(int x, int y)
    {
        return x > this.x && y == this.y;
    }
}

このコードは、C#言語で書かれた将棋の駒のクラス Kyouを定義しています。 Kyou クラスは、 Piece クラスを継承しています。

Kyou クラスには、引数としてx座標とy座標を持つコンストラクタがあります。このコンストラクタは、 Piece クラスのコンストラクタを呼び出します。

この Kyou クラスは、「香車」を表しています。香車は、直線状に前に進むことができ、その範囲は1マス以上です。

Kyou クラスには、 CanMoveTo メソッドがあります。これは、駒が指定された座標に移動できるかどうかを判断するために使用されます。このメソッドは、x座標が現在の座標よりも大きく、y座標が現在の座標と同じである場合に true を返します。つまり、香車は縦方向に前に進むことができますが、斜めには進むことができません。

駒を移動する

移動が可能なら、移動するようにPieceクラスにコードを追加してみます

// 駒を移動し、移動できるかどうかを確認するメソッド
public bool MoveTo(int x, int y)
{
    if (CanMoveTo(x, y))
    {
        this.x = x;
        this.y = y;
        Console.WriteLine($"{GetType().Name}を{x},{y}に移動しました。");
        return true;
    }
    else
    {
        Console.WriteLine($"{GetType().Name}は{x},{y}には移動できません。");
        return false;
    }
}

このコードは、将棋の駒を移動するためのメソッドを定義しています。

メソッド名は MoveTo で、引数として移動先の x 座標と y 座標を受け取ります。メソッドの戻り値は bool 型で、移動が成功した場合には true、失敗した場合には false を返します。

このメソッドでは、移動が可能かどうかを CanMoveTo メソッドで確認し、移動が可能であれば指定された x 座標と y 座標に駒を移動させます。移動に成功した場合には、移動した駒の種類と移動先の座標を出力します。移動が失敗した場合には、移動できない旨を出力します。

なお、このコードの中で使われている GetType().Name は、オブジェクトの型を取得してその名前を文字列として返すメソッドです。例えば、王将の場合は “Fu"、飛車の場合は “Kyou" などが返されます。

ここまでまとめたサンプル

Piece fu = new Fu(2, 7);
fu.MoveTo(2, 6);

abstract class Piece
{
    // 駒の位置を表すフィールド
    protected int x;
    protected int y;

    // コンストラクタで駒の位置を指定
    public Piece(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    // 駒を移動し、移動できるかどうかを確認するメソッド
    public bool MoveTo(int x, int y)
    {
        if (CanMoveTo(x, y))
        {
            this.x = x;
            this.y = y;
            Console.WriteLine($"{GetType().Name}を{x},{y}に移動しました。");
            return true;
        }
        else
        {
            Console.WriteLine($"{GetType().Name}は{x},{y}には移動できません。");
            return false;
        }
    }

    abstract protected bool CanMoveTo(int x, int y);
}

class Fu : Piece
{
    public Fu(int x, int y) : base(x, y)
    {
    }
    // 歩は前に一歩だけ進むことができる
    protected override bool CanMoveTo(int x, int y)
    {
        return x == this.x && y == this.y - 1;
    }
}

このコードは、将棋の駒を表すクラスを定義し、そのうちの「歩」の動きを制御するためのコードです。

まず、Pieceという抽象クラスが定義されています。このクラスは、駒の位置を表す x, y フィールドと、駒を移動するための MoveTo メソッドが定義されています。MoveTo メソッドでは、引数で指定された座標に駒を移動しようと試みます。その際、移動できるかどうかを CanMoveTo メソッドで確認します。CanMoveTo メソッドは、派生クラスで実装されるため、駒ごとに異なる動きを実現することができます。

次に、Fu というクラスが定義されています。Fu クラスは Piece クラスを継承しており、親クラスのコンストラクタを呼び出して x, y フィールドを初期化しています。また、CanMoveTo メソッドをオーバーライドして、歩が前に一歩だけ進むことができるようにしています。

最後に、インスタンス化された Fu オブジェクト Fu を定義し、MoveTo メソッドで座標を指定しています。MoveTo メソッドでは、CanMoveTo メソッドが呼び出され、その結果に応じて駒の位置を移動するかどうかが決定されます。

実行結果

Piece fu = new Fu(2, 7);
fu.MoveTo(2, 6); // Fuを2,6に移動しました。
Piece fu = new Fu(2, 7);
fu.MoveTo(2, 5); // Fuは2,5には移動できません。

盤面の初期化(調整用)

// 盤面の初期化
var board = new Piece[,]
{
    {new Kyou(0, 0), new Kei(0, 1), new Gin(0, 2), new Kin(0, 3), new Ou(0, 4), new Kin(0, 5), new Gin(0, 6), new Kei(0, 7), new Kyou(0, 8)},
    {null, new Hisha(1, 1), null, null, null, null, null, new Kaku(1, 7), null},
    {new Fu(2, 0), new Fu(2, 1), new Fu(2, 2), new Fu(2, 3), new Fu(2, 4), new Fu(2, 5), new Fu(2, 6), new Fu(2, 7), new Fu(2, 8)},
    {null, null, null, null, null, null, null, null, null},
    {null, null, null, null, null, null, null, null, null},
    {null, null, null, null, null, null, null, null, null},
    {new Fu(6, 0), new Fu(6, 1), new Fu(6, 2), new Fu(6, 3), new Fu(6, 4), new Fu(6, 5), new Fu(6, 6), new Fu(6, 7), new Fu(6, 8)},
    {null, new Kaku(7, 1), null, null, null, null, null, new Hisha(7, 7), null},
    {new Kyou(8, 0), new Kei(8, 1), new Gin(8, 2), new Kin(8, 3), new Gyoku(8, 4), new Kin(8, 5), new Gin(8, 6), new Kei(8, 7), new Kyou(8, 8)}
};
// 盤面の表示
for (int row = 0; row < 9; row++)
{
    for (int columns = 0; columns < 9; columns++)
    {
        Piece piece = board[row, columns];
        Console.Write(piece == null ? " " : piece.GetType().Name);
    }
    Console.WriteLine();
}
KyouKeiGinKinOuKinGinKeiKyou
 Hisha     Kaku 
FuFuFuFuFuFuFuFuFu
         
         
         
FuFuFuFuFuFuFuFuFu
 Kaku     Hisha 
KyouKeiGinKinGyokuKinGinKeiKyou
Fuは2,5には移動できません