インターフェイスを含むシミュレーションのこのOOP設計は悪いですか?


13

私は吸血鬼、オオカミ、人間、トラックをシミュレートするために自分の小さなOOPプログラムを設計しており、インターフェイスに関する私自身の限られた理解を実装しようとしています。

私はまだここで抽象化しており、まだコードの実装がないので、OOP設計の問題です...私は思う!)

これらのクラス間の「共通の振る舞い」を探して、インターフェースとして実装するのは正しいですか?

たとえば、ヴァンパイアとオオカミの噛みつき...噛み付きのインターフェースが必要ですか?

public class Vampire : Villain, IBite, IMove, IAttack

トラックについても同様です...

public class Truck : Vehicle, IMove

そして人間のために...

public class Man : Human, IMove, IDead

私の考えはここにありますか?(あなたの助けに感謝)


14
動物、野菜、ミネラルがアプリケーション実装の良い例になることはめったにありません。実際の実装は、一般的のような、より抽象的であるIEnumerableIEquatableなど、
ロバート・ハーヴェイ

6
あなたのオブジェクトがあなたのソフトウェアで何をしようとしているのかについて一つの言及があります(「噛みつき」)。ソフトウェアは通常、何かを行うように設計されており、オブジェクトモデルを特性のみに基づいて作成することは、どこにも先行していません。
トフロ

@tofro IBiteには、(1)別の「生命/エネルギー」レベルの低下(2)「血液」グラフィックの出現または呼び出し、および(3)シミュレーション統計の更新に関する動作を実装する複数のメソッドが含まれるつもりでしたデータ(NoOfBitesなど)。さまざまなメソッドの動作を実装するためにインターフェイスが最適に使用されていることを理解できると思います。
user3396486

2
クラスHuman、Vampire、VehicleはIMoveインターフェースを既に実装していませんか?サブクラスに明示的に実装しすぎる必要があるのはなぜですか?
ピエールアラード16

このインターフェイスはすべて本当に必要ですか?Pythonでは、幸いなことに、このようなものは必要ありません。ehichは本当に爽快な変更でした(私の最初の言語はObject Pascalでした)。また、仮想メソッドは、場合によってはより良いソリューションかもしれません。
アジャシャ

回答:


33

一般に、クラスの共通の特性のためのインターフェースが必要です。

コメントで@Robert Harveyに半同意します。彼は通常、インターフェイスはクラスのより抽象的な機能を表すと言いました。それにもかかわらず、私はより具体的な例から始めることは抽象的なことを考え始める良い方法だと思います。

あなたの例は技術的には正しいのですが(つまり、はい、吸血鬼とオオカミの両方が噛み付いているので、そのためのインターフェースを持つことができます)、関連性の問題があります。各オブジェクトには数千の特性があります(たとえば、動物は毛皮を持っている、泳ぐことができる、木に登るなど)。それらすべてのインターフェースを作成しますか?非常に少ない。

通常は、意味のあるもののインターフェイスをアプリケーション全体でグループ化する必要があります。たとえば、ゲームを構築している場合、IMoveオブジェクトの配列を作成して、その位置を更新できます。これを行いたくない場合、IMoveインターフェースを使用してもほとんど役に立ちません。

重要なのは、過剰なエンジニアリングをしないことです。そのインターフェースをどのように使用するかを考える必要があり、共通のメソッドを持つ2つのクラスは、インターフェースを作成するのに十分な理由ではありません。


1
各オブジェクトに数千の属性がないことを願っています。
ガーデンヘッド

4
oop属性のような属性ではなく、文法属性/特性(enumerable、comparableなど):D。言葉の選択が悪い。
-Paul92

3
有用なインターフェースは、使用するインターフェースであることに注意してください。例えば、IBite特に有用ではないですが、あなたが望むかもしれないIAttack、あなたが攻撃を行うすべてのものの上に作業することができますので、またはIUpdateあなたは、すべてのアップデートを実行できるように、またはIPhysicsEnabledあなたは、彼らになどを物理学を適用することができるように
アナクシマンドロス

1
この答えはいくつかの非常に良い点を提起します。最後の段落でかなりうまくまとめています。少なくとも提供される詳細レベルでできる限り。
モニカとの軽さのレース

1
commonsメソッドのグループ化は、抽象クラスにより適しています。インターフェイスは、一部のオブジェクトの同じ実装をグループ化するのではなく、実装する人を尊重する必要があるコントラクトを設計するために作成されます。
ウォルフラット

28

多数の単一メソッドインターフェイスを作成しているように見えます。これは表面上は問題ありませんが、インターフェイスはそれらを実装するクラスによって所有されていないことに注意してください。それらは、それらを使用するクライアントによって所有されます。クライアントは、何かが移動して攻撃できるものである必要があるかどうかを決定します。

私が持っている場合Combatにクラスをfight()する方法、その方法は、おそらく両方を呼び出す必要がありmove()attack()同じオブジェクト上を。これは、呼び出しと通過が可能なICombatantインターフェースの必要性を強く示唆しています。これは、オブジェクトを取得してキャストして、オブジェクトが移動できるかどうかを確認するよりもクリーンです。fight()move()attack()fight()IAttackIMove

それはあなたも持っていないという意味ではありません IMove IAttackインターフェース。一部のクライアントがそれらを必要とせずにそれらを作成しないことを願っています。逆に、オブジェクトの移動と攻撃の両方を行う必要のあるクライアントがなければ、そのICombatant必要はありません。

この単純なインターフェイスの見方は、次の例を好む人が多いため、しばしば失われます。最初に公開されるインターフェイスはライブラリにあります。残念ながら、図書館はクライアントが何であるかを知りません。そのため、クライアントのニーズのみを推測できます。従うべき最良の例ではありません。


1
くそーこれはいいです。ゲームは、OOPを使用して説明するための本当に良い方法のように思えます。
ジェフ

6
@JeffOを使用して、かなり大きなゲームを実際に実装し、OOPがホット混乱であり、コンポーネントベースのシステムまたはデータ指向の設計の方が良いことに気付くまで。
ダークホッグ

「インターフェイスは、それらを使用するクライアントが所有しています」
-Tibos


1
ライブラリとアプリケーションの違いを+1するために、私はしばしば(多すぎる?:/)片方だけに適合し、もう一方には適合しないものをたくさん読みます。
ウォルフラット

3

さまざまな組み合わせの機能を持つオブジェクトのコレクションを使用するのが一般的かどうか、およびコードでアクションを実行する必要があるかどうかを検討します それをサポートするコレクション内のそれらのアイテム。もしそうなら、そして何らかのアクションに対して有用なサポートを持たないオブジェクトに賢明な「デフォルトの振る舞い」があるならば、有用な振る舞いをすることができるものだけでなく、幅広いクラスによって実装されるインターフェースを持つことは役に立つかもしれません。

たとえば、ウーズを持つことができるのは数種類のクリーチャーのみであり、そのようなクリーチャーにNumerOfWoozlesプロパティを持たせたいとします。そのようなプロパティが、ウーズを持つことができるクリーチャーによってのみ実装されるインターフェースにある場合、混合タイプのクリーチャーのコレクションによって保持されているウーズの総数を見つけたいコードは、次のように言う必要があります。

int total = 0;
foreach (object it in creatures)
{
   IWoozleCountable w = trycast(it, IWoozleCountable);
   if (w != null) total += w.WoozleCount;
}

ただし、WoozleCountがCreature / ICreatureのメンバーである場合、常にゼロを返すCreatureのデフォルトのWoozleCount実装をオーバーライドするサブタイプはほとんどありませんが、コードは次のように簡略化できます。

int total = 0;
foreach (ICreature it in creatures)
   total += it.WoozleCount;

一部の人々は、すべてのCreatureにいくつかのサブタイプにのみ有用なWoozleCountプロパティを実装するという考えに迷い込むかもしれませんが、プロパティは、それらのタイプであることが知られているアイテムで役立つかどうかに関係なく、すべてのタイプに意味があります、そして、「キッチンシンク」インターフェースは、trycastオペレーターよりもコード臭が少ないと考えています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.