1. ホーム

[解決済み】ゲッターとセッターは設計が悪いのか?矛盾するアドバイスが見受けられる【重複あり

2022-04-17 22:37:05

質問

私は現在、Javaでいくつかの異なるモードを持つ簡単なゲームを作っています。メインのGameクラスを拡張して、メインのロジックを他のクラスの中に入れています。それでも、メインのゲーム・クラスはかなり重いです。

私のコードをざっと見たところ、ゲッターとセッターが大部分(60%)を占めており、残りの部分はゲームのロジックに本当に必要なものでした。

Googleで検索すると、ゲッターとセッターは悪だと言う人もいれば、良いOOの実践と素晴らしいプログラムのために必要だと言う人もいます。

では、どうすればいいのでしょうか?どっちがいいんだろう?プライベート変数のゲッターとセッターを変更すべきなのか、それともこのままで良いのか?

どのように解決する?

また、ほとんどの場合、セッターを使用しても、意味のない値を設定することができるため、カプセル化を解除してしまうという指摘もあります。例えば、ゲームのスコアカウンタが常に上昇するものである場合、その代わりに

// Game
private int score;
public void setScore(int score) { this.score = score; }
public int getScore() { return score; }
// Usage
game.setScore(game.getScore() + ENEMY_DESTROYED_SCORE);

であるべきです。

// Game
private int score;
public int getScore() { return score; }
public void addScore(int delta) { score += delta; }
// Usage
game.addScore(ENEMY_DESTROYED_SCORE);

これは少し安直な例かもしれません。私が言いたいのは、ゲッター/セッターとパブリックフィールドについて議論すると、オブジェクトが互いの内部状態を親密に操作し、それゆえ密接に結合しすぎているという大きな問題が見えなくなってしまうことがよくあるということです。

やりたいことを直接やるメソッドを作ろうということです。例えば、敵の「生きている」というステータスを設定する方法です。setAlive(boolean alive)メソッドを持ちたくなるかもしれません。その代わり、次のようなメソッドを用意する。

private boolean alive = true;
public boolean isAlive() { return alive; }
public void kill() { alive = false; }

この理由は、もし実装を変更してモノが "alive" というブール値を持たず、代わりに "hit points" という値を持つようにしても、先に書いた二つのメソッドの契約を破棄せずにそれを変更することができるためです。

private int hp; // Set in constructor.
public boolean isAlive() { return hp > 0; } // Same method signature.
public void kill() { hp = 0; } // Same method signature.
public void damage(int damage) { hp -= damage; }