ラッパーに多くのパススルー関数を記述しないようにするにはどうすればよいですか?


13

共通の基本型の別のクラスをラップするクラスがあります。基本型インターフェースは非常に大きいため、これには多くのパススルー関数の作成が含まれます。これを回避する方法を探しています。

例を作りましょう:

      Car
     /   \
Volvo     VolvoWithTrailer

ここで、VolvoWithTrailerの車のインターフェイスにすべての関数を実装し、ラップされたVolvoオブジェクトで適切な関数を呼び出す必要があります。ただし、GetMaxSpeed()は、より低い値を返します。基本的に次のような多くの機能があります

int VolvoWithTrailer::GetNumSeats() {
  return mVolvo.GetNumSeats()
}

これを解決する明白な方法は、VolvoWithTrailerをVolvoのサブクラスにすることです。

    Car
     |
   Volvo
     |
VolvoWithTrailer

しかし、それは継承よりも構成を優先するという原則に違反しているようです。

これらのすべてのラッパー(言語はC ++)を書くことを他にどのように回避できますか?または-それがあなたの立場である場合-なぜ私はそれらを書くだけですか/単に継承を使用するのですか?これに役立つテンプレートの魔法はありますか?


2
これをやりすぎて、Javaで考えてはいけません。「予告編」インターフェースはどうですか?VolvoWithTrailerはVolvoを拡張し、Trailerインターフェースを実装しますか?

7
理にかなっている場合にのみ、継承よりも合成を優先します。
ロバートハーベイ

@RobertHarvey:+1。それはガイドラインであり、「原則」ではなく、絶対的な命令でもありません。
メイソンウィーラー

Pythonでは、これをイントロスペクション(C#でリフレクションと呼びます)で解決できます。
user16764

1
IDEはコード生成を処理しませんか?
エイミーブランケンシップ

回答:


5

私の意見では、プログラムの長期的な安定性と保守性を向上させるために、必要なものは何でも書く必要があります。今日20行のコードを書くことを避ける意味は何ですか、このコードを使用するものに触れるか、このクラスを維持するために戻ってくるたびに、今日の時間を入れなかったために余分な5分以上かかりますか?

それで、質問は「何を書く必要がありますか」になります。決定的な答えを出すのに十分な情報を提供してくれるとは思わないので、決断を下す際に考えられることいくつか挙げておきます。

1.現在または近い将来、Trailerオブジェクトを単独で持つ必要がありますか?
もしそうなら、あなたはすでにどちらか一方をラップしなければならないので、あなたは両方の合成されたオブジェクトのラッパーを作るためのかなり良い議論を持っています。一貫性があるかもしれません。

2. 3つのタイプ(Car、Trailer、CarWithTrailer)のいずれかは、開発者が頻繁にアクセスするコードの領域にありますか?
もしそうなら、非常に注意してください。間違ったものを選択することの影響は、コードに触れるたびに非常に費用がかかるためです。そうでなければ、あなたが決めたものに何の違いももたらさないかもしれません。ただ方向を選んでそれと一緒に行きます。

3.最も理解しやすいものは何ですか?
あなたの後ろにいる誰かがあなたがやろうとしていることをすぐに「取得」するだろうというアプローチがありますか?チームメイトには、特定のバイアスがあり、1つのアプローチを維持するのが難しくなる可能性がありますか?すべてが等しい場合、認知負荷が最も低いソリューションを選択します。

4.あるアプローチを別のアプローチよりも使用することの追加の利点はありますか?
私に飛び出すことの一つは、あなたのCarWithTrailerWrapperを包むことができ、それを書いた場合、ラッパーアイデアは明確な利点を持っていることで任意の車とどの CarWithTrailerにトレーラーを。次に、すべてのパススルーメソッドを記述します、各Carクラスに対して1回ではなく、一だけ記述します。

これにより、車やトレーラーを追加するにつれて、パススルーメソッドを記述するための初期投資がはるかに安くなります。また、VolvoまたはVolvoWithTrailerに直接結合する誘惑を減らし、CarWithTrailerWrapperへの結合の結果を減らします。これは、その1つの実装だけでより多くのことができるためです。

拡張メソッドを使用することで無料で得られる明らかな利点があるかもしれませんが、私はそれらを見ません。

わかりましたので、自明ではないアプリケーションのために、先に進んでパススルーメソッドを埋めることについて話をしたようです。

私はC ++プログラマーではないので、どのコード生成ツールを使用できるかわかりません。私が使用するIDEでは、インターフェイスからメソッドを生成できます。また、パススルーの作成を非常に簡単にするコードテンプレート追加できます。これを行うIDEにアクセスできない場合は、実際にExcelにコードを書いてもらうことができます


3

基本型インターフェースは非常に大きいため、これには多くのパススルー関数の作成が含まれます。

そして、あなたの問題があります。

インターフェイスは1つの責任のみを処理する必要があります。それらを薄く集中させることで、デコレータ、プロキシ、またはその他のラッパーの場合に必要なパススルー作業の量を制限します(クラスシンプラーを使用、テスト、保守、および拡張することに加えて)。


5
あ、何?1つのクラスは複数のインターフェイスを実装でき、インターフェイスは相互に継承できます。そのため、インターフェースが非常に小さい場合でも、それを実装するクラスが多くの関数またはパススルー関数を必要とするかどうかには関係ありません。クラスが小さく、より明確に定義されているほど、パススルー関数必要になる可能性が高くなります。
エイミーブランケンシップ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.