2017-01-05 19 views
0

これは重複していると確信していますが、私は正しい答えを探していますか分かりません。またはそれが私の質問に答えることを理解する。 1の場合、私のインターフェースを間違って使用していると思います。 1のために私はSOLIDのルールを破り、それをきれいにしようとしています。たとえば、IReelWindowです。私はReelWindowTumbleに固有のものがありますが、他のReelWindowsは実装されていないエラーを投げないでください。私はそれを複数のインターフェイスに分割し始めましたが、ITumbleの新しいインターフェイスを作成してもまだIReelWindowから継承していても、私はもはやReelWindowTumbleの関数にアクセスできませんでした。問題は機能コードにあります。ここで渡す一般的な型を実装してください

public interface IReelWindow 
{ 
    //stuff declared 
    void PopulateWindowTumble(); 
    void PopulateWindow(int[] currentStops); 
} 
public class ReelWindow : IReelWindow 
{ 
// implements most of it throwing exceptions when I don't use it. 
    public void PopulateWindow(int[] currentStops) 
    { 
    } 
    public void PopulateWindowTumble() 
    { 
     throw new NotImplementedException(); 
    } 
} 
public class ReelWindowTumble : IReelWindow 
{ 
// implements most of it throwing exceptions when I don't use it. 
    public void PopulateWindow(int[] currentStops) 
    { 
    } 
    void PopulateWindowTumble() 
    { 

    } 
} 
public class ReelWindowIndependent : IReelWindow 
{ 
// implements most of it throwing exceptions when I don't use it. 
    public void PopulateWindow(int[] currentStops) 
    { 
    } 
    public void PopulateWindowTumble() 
    { 
     throw new NotImplementedException(); 
    } 
} 

私は新しいIReelWindowを宣言し、クライアントの入力に基づいて新しいReelWindowを作成します。これは、ReelWindowを使用したいところのどこでもIReelWindowを渡すだけで、うまくいきます。 これは私のインターフェイスの適切な使い方ではないと思います。 ICloneableを使用する場合、私はICloneableという新しいオブジェクトを宣言せず、それを渡します。 しかし私の意図はGeneric ReelWindowタイプを作成することです。クライアントが作成するウィンドウのタイプは気にしません。私はちょうど私がそれらを具体的に使用するときにどのような機能を持つべきかを強制したい。
同一の強力な型が渡された複数の関数を作成せずに渡すことができる汎用のReelWindowを宣言するにはどうすればよいですか?

public static IReelWindow CreateReelWindow(WindowType userSelectedWindowType, Paytable paytable) 
{ 
    IReelWindow _reelWindow; 
    if (userSelectedWindowType == WindowType.Standard) 
    { 
     _reelWindow = new ReelWindow(paytable.ColLengths, paytable.ReelContainer.Reels, paytable.WindowWidth,      paytable.Lineset, paytable.ReelContainer.TotalPhysicalReelStop); 
    } 
    else if (userSelectedWindowType == WindowType.Tumble) 
    { 
     _reelWindow = new ReelWindowTumble(paytable.ColLengths, paytable.ReelContainer.Reels, paytable.WindowWidth, paytable.Lineset, paytable.ReelContainer.TotalPhysicalReelStop); 
    } 
    else if (userSelectedWindowType == WindowType.Independent) 
    { 
     _reelWindow = new ReelWindowIndependent(paytable.ColLengths, paytable.ReelContainer.Reels, paytable.WindowWidth, paytable.Lineset, paytable.ReelContainer.TotalPhysicalReelStop, paytable.ReelLengths, paytable.ReelStarts); 
     } 
     else 
      throw new ApplicationException("Unknown window type selected by user. Cannot continue."); 
     return _reelWindow; 
    } 

後で私のコードで私はreelwindowsを使用し、私は、関数はそれに応じて使用しますreelwindowの種類を気にしないようにのみ「IReelWindow」を渡します。

public abstract class AEval 
{ 
    public abstract double Evaluate(IReelWindow reelWindow, ref string flags, int currentStopsWeight); 
    public abstract double EvaluateVerbose(IReelWindow reelWindow, ref string flags, int currentStopsWeight); 
} 
+1

あなたは、インターフェイスの実装からNIEを投げることはコードのにおいですが、意味のあなたの質問に答えるために、よりインタフェースの詳細、およびその使用せずにそのハードということですね。 – Jamiec

答えて

0

あなたの周りに渡しているオブジェクトが_reelWindowであり、それはIReelWindowを実装しながら、それはIReelWindowオブジェクトではありません。 ReelWindow、ReelWindowTumble、ReelWindowIndependentなどの派生型の1つです。これらの派生型はそれぞれ、クライアントが同じように扱う必要があります(上記のように)。

ReelWindowはインターフェイスから2つのメソッドを実装していますが、ReelWindowTumbleはインターフェイスから3つのメソッドを実装し、ReelWindowIndependentはインターフェイスから10のメソッドを実装しています。また、インターフェイスに実装するメソッドは最大10個あります。

ReelWindowはNotImplementedException(NIE)で8つのメソッドを持ち、ReelWindowTumbleは7つのメソッドNIEを持ち、ReelWindowIndependentは0つのメソッドNIEを持っています。

お客様のクライアントコードはどうですか?まあ、これが意味を成し遂げるためには、_reelWindowを使って作業しているときに、クライアントコードがすべてのインタフェースメソッドを呼び出す必要があります。つまり、ReelWindowIndependentはNIEメソッドを持たないため、クライアントコードでうまく動作するはずです。

あなたの本当の問題はNIEです。これらの例外を削除し、代わりにnullを返します。次に、クライアントコードで、制御のフロー中に、「返されたオブジェクトがnullの場合は、このセクションをスキップする」という効果を追加することができます。

すべてのオブジェクトは「オブジェクト」を継承しています。あなたのインターフェースの強く型付けされたリターンオブジェクトは、 'オブジェクト'としても返すことができます。つまり、厳密に型指定されたオブジェクトはnullに設定できます。繰り返します:強く型付けされた戻り値を持つメソッドのnull値を返し、クライアントコードでnullを処理してみます。今度は、インターフェイスメソッドに戻り値がない場合は、voidとマークされます。クライアントコードでnullをチェックする心配もNIEも必要ありません。メソッドは空白のままにすることができ、文字通り何もしません。これを熟考すれば、強く型付けされた戻り値を使用しないインターフェース設計に努めるかもしれません。 Jamiecのコメントには、インターフェイスについてもっと知る必要があります。

+0

インターフェイスが正しく使用されていますか?そして、私はNIEの扱いを別にする必要がありますか?同じ臭いがプログラムをクラッシュさせるよりもうまく処理されたようです。 – user3281977

+0

いいえ、同じにおいではありません。 IDriveCarというインターフェースを想像してみてください。また、AutomaticCarとStandardCarの2台の車があります。どちらもIDriveCarを実装します。 ShiftGears()というメソッドを実装しているとふりましょう。自動車はそのすべての自動車の後で、ShiftGears()の実装方法で "何もしません"。 StandardCarは、 "ギアシフトレバーを次のギアに動かすために手を使う"とそれを実装し、AutomaticCarは "何もしない"でそれを実装します - それはNIEを投げて車をクラッシュさせることです! – sapbucket

+0

OK。私はその作品を手に入れます。しかし、あなたが新しい車(自動車または標準)を宣言するとき、あなたは新しいIDriveCarを宣言していますか?または、私は車を運転するためにShiftGears()を強制的に実装した新しいAutomaticCarを宣言していますか? – user3281977

関連する問題