質問: 将棋の駒台クラスを作るにあたり、どのような設計にすれば良いものか悩んでいます。 ArrayListを使い駒台が所持している駒を保持するという方法を取ろうと思っていましたが、以下のような設計の方が色々と都合が良いのです。 駒台に乗る駒は飛、角、金、銀、桂、香、歩の7種類しかありません。 そこで、この7種の駒をそれぞれ何枚ずつ持っているかという事をint[7]という配列のようなもので管理する。 この方法で実現したいのですが、この構造だと困ることもあるわけです。 駒台クラスに必要なメソッドとして例えば、駒大に駒を追加する(引数は駒クラス)というものがあります。 引数から、配列のどの要素に+1するのかというのを決定するにはif/switchで条件分岐するという方法しか思いつきません。 配列名[引数で受け取った駒クラス] ++;この様に処理できればうまくいくわけですが... javaのハッシュマップ機能を使えば実現できるわけですが、クラスを取得し、それをキーとするっていうのは美しくないし綺麗じゃないんですよね。 (クラスを取得する事をリフレクションと言うのでしょうか?) そもそもクラスを配列の添字として使うのは良いやり方なのでしょうか。
回答: みなさんと同じようなことに過ぎませんが、「あるものに対する関連情報をenumとして宣言的に定義」という方法があります。本件についていえば駒に関連する色々な情報があるように思えるのであちこちの連想コレクションを使って分散して定義するよりは一括して集中定義できるので自分は好んで使います。これがオブジェクト指向的かどうかと言われれば「駒の種類」をどんなクラスとして捉えるか如何にかかると思います。 メタ情報の代表はクラスオブジェクトですがクラスメソッドやクラスフィールドが必ずしも都合よく定義できない(※)のでメタ情報を保持するなんらかのメタクラスがほしくなります。必ずしもenumでなくてもよいのですがインスタンスの宣言が `static final Meta 王 = new Meta("王", ...);` ではなく、 `王(...),` と書けば済むというだけの理由でenumの方が若干短く書けます。 ``` enum 駒の種類 { 王(...), 金(..., 0), 銀(..., 1), ... 歩(..., 6), ; private int komadaiIndex; 駒の種類(...) { this(..., -1); } 駒の種類(..., int komadaiIndex) { ... this.komadaiIndex = komadaiIndex; } ... public int getKomadaiIndex() { if (komadaiIndex == -1) throw new InternalError(name() + " has no komadaiIndex"); return komadaiIndex; } } class 駒Model { public abstract 駒の種類 get駒の種類(); ... } ``` ※:クラスメソッドやクラスフィールドが必ずしも都合よく定義できない 例えばstaticメソッドやstaticフィールドをクラスメソッド・クラスフィールドにみたてて使える場合もあると思いますがこれらは継承できないので、以下のように書けないのです。 ``` Class extends 駒Model> 駒ModelClass = ...; int komadaiIndex = 駒ModelClass.getKomadaiIndex(); ```