暗黙的に別のクラスに変換することのみを目的とするクラスを作成するのは悪いことですか?


10

Circleオブジェクトを作成できるライブラリを使用していて、円の半径と中心を指定してオブジェクトを定義できる状況を想像してみてください。ただし、何らかの理由で、必要なflavourパラメーターも受け取ります。ここCircleで、自分のアプリで本当に使用する必要があるとしましょう。ただし、アプリの目的で、フレーバーをFlavours.Cardboard毎回に設定できます。

この「解決」をするために、私は自分の作成Circleのみとり異なる名前空間でクラスをradiusし、centerパラメータとしてではなく、外部ライブラリのへの暗黙のコンバータがあるCircleだけで作成したクラスCircle(this.radius, this.center, Flavours.Cardboard)のオブジェクトを。したがって、他のタイプのが必要なすべての場所でCircle、自動変換を実行します。

そのようなクラスを作成するとどうなりますか?より良い解決策はありますか?私のアプリケーションが、この外部ライブラリの上に構築されたAPIであり、他のプログラマーが使用することを目的としていた場合、何か違いはありますか?


これはアダプタパターンのバリエーションのようですが、ここでは疑わしい値のようです(これは、パラメータの設定を回避するための便宜にすぎません)。
Robert Harvey

5
MakeCircle 関数を作成してみませんか?
user253751 2016年

1
@immibis Thayは私の最初の考えでした。ゲームを作成しているときはmakePlayer、それ自体に沿って関数を作成することがよくあります。その関数自体は、プレーヤーを配置するための座標のみを受け入れますが、より複雑なコンストラクターに委任します。
発がん性物質2016年

回答:


13

必ずしも悪いことではありませが、暗黙の変換が最良のオプションであることは非常にまれです。

問題があります。

  1. 暗黙的な変換はあまり読みやすくありません。
  2. 新しいオブジェクトを作成しているため、元のオブジェクトに加えられた変更は、変換先のオブジェクトには反映されず、バグが発生します。
  3. オブジェクトを捨てる場合、それはクリーンアップするための余分なゴミです。
  4. 問題がある場合は、モノが作成されたときではなく、変換が発生したときに発生するため、バグの追跡が困難になります。

一般的に、より良い解決策があります。

  1. 内部で他のクラス/フレームワークを使用する独自のシンラッパーを作成します。
  2. 必要なコンストラクター引数を取り、修正された引数を提供するヘルパーメソッドを作成し、不要な引数を指定せずに実際のオブジェクトを返します。
  3. 問題のあるクラスから継承し、独自のより優れたコンストラクタを提供します。
  4. 追加の引数を渡すことは実際にはそれほど大きな問題ではないことを理解してください。

個人的には、#2が実装が最も簡単で、設計の負担が最も少ないと思います。他の人は、状況と、これらのクラスで他に何をしようとしているのかを考えれば、大丈夫です。

暗黙の変換は最後の手段であり、私が作成しようとしているC ++スタイルのファンクターがある場合にのみ、本当に価値があるように思えます-暗黙的にデリゲート型に変換する戦略オブジェクト。


1

説明しているシナリオを考えると、これは部分的な関数の適用の観点から考えることができます。

コンストラクターは関数です(少なくとも理論的には、C#では、コンストラクターを呼び出す「ファクトリー関数」を作成できます)。

Func<double, Point, Flavour, Circle> MakeCircle = (r, p, f) => new Circle(r, p, f);

部分的な適用については、以下で十分です:

public static Func<T1, T2, R> Partial<T1, T2, T3, R>(this Func<T1, T2, T3, R> func, T3 t3)
   => (t1, t2) => func(t1, t2, t3);

これで、2つのパラメーターのみを必要とするコンストラクターを取得できます。

Func<double, Point, Circle> MakeCardboardCircle = Circle.Partial(Flavours.Cardboard)

これで、目的のパラメーターを持つファクトリー関数ができました。

Circle c = MakeCardboardCircle(1.0, new Point(0, 0)))

ところで、これは上記のオプション2と明らかに同等です。

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