2017-01-05 3 views
0

zu übergeben Ich bin sicher, das ist doppelt, aber ich bin nicht sicher, ob ich nach den richtigen Antworten suche. Oder zu verstehen, dass es meine Frage beantwortet. Für 1 Ich denke, ich benutze meine Schnittstelle falsch. Für 1 brich ich die Regeln von SOLID und versuche, es aufzuräumen. Zum Beispiel IReelWindow. Ich habe die Dinge in dort spezifisch ReelWindowTumble, die andere ReelWindows nicht verwenden und nicht implementierte Fehler werfen. Ich begann es in mehrere Schnittstellen zu brechen, aber ich fand nicht mehr Zugriff auf Funktionen für ReelWindowTumble, obwohl ich eine neue Schnittstelle für ITumble erstellt und immer noch geerbt von IReelWindow. Das Problem liegt im Funktionscode.Implementieren Sie einen generischen Typ um

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(); 
    } 
} 

Hier erkläre ich einen neuen IReelWindow und einen neuen ReelWindow Eingabe basierend auf Client erstellen. Das funktioniert ganz gut, da ich einfach IReelWindow überall hin durchführe, wo ich ein ReelWindow benutzen möchte. Ich glaube nicht, dass dies die richtige Verwendung meiner Schnittstelle ist. Wenn ich ICloneable verwende, deklariere ich kein neues Objekt von ICloneable und gebe es weiter. Aber meine Absicht ist es, einen generischen ReelWindow Typ zu erstellen. Es ist mir egal, welche Art von Fenster der Client erstellt. Ich möchte nur durchsetzen, welche Funktionen es haben sollte, wie ich sie speziell verwende.
Wie deklariere ich eine generische ReelWindow, die ich weitergeben kann, ohne mehrere Funktionen zu erstellen, die identisch sind, aber starke Typen übergeben haben?

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; 
    } 

Später in meinem Code verwende ich die reelwindows, und übergeben Sie nur in ‚IReelWindow‘ wie mir egal, welche Art von reelwindow, die Funktion, die sie entsprechend verwenden.

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

Sie haben Recht, dass das Werfen von NIE von Schnittstellenimplementierungen ein Code-Geruch ist, aber ohne mehr Details der Schnittstelle und seiner Verwendung ist es schwierig, Ihre Frage sinnvoll zu beantworten. – Jamiec

Antwort

0

Das Objekt, das Sie rund um ist _reelWindow vorbei sind und während es IReelWindow implementiert, es ist kein IReelWindow Objekt. Stattdessen ist es einer Ihrer abgeleiteten Typen: ReelWindow, ReelWindowTumble, ReelWindowInpendent usw. Jeder dieser abgeleiteten Typen sollte von Ihrem Kunden (wie Sie angegeben haben) gleich behandelt werden.

Nehmen wir an, ReelWindow implementiert 2 Methoden von der Schnittstelle, ReelWindowTumble implementiert 3 Methoden von der Schnittstelle und ReelWindowIndependent implementiert 10 Methoden von der Schnittstelle. Und die Schnittstelle hat maximal 10 Methoden zu implementieren.

Mit der Sprache Ihres Beispiels bedeutet das, dass ReelWindow 8 Methoden mit NotImplementedException (NIE), ReelWindowTumble 7 Methoden NIE und ReelWindowIndependent 0 Methoden NIE hat.

Was ist mit Ihrem Client-Code? Nun, damit all dies Sinn macht, sollte Ihr Client-Code alle 10 der Interface-Methoden aufrufen, während Sie mit _reelWindow arbeiten. Das bedeutet auch, dass ReelWindowIndependent mit meinem Beispiel gut mit dem Client-Code funktionieren sollte, da es keine NIE-Methoden gibt.

Ich würde sagen, dass Ihr echtes Problem die NIE's ist. Entfernen Sie diese Ausnahmen und geben Sie stattdessen null zurück. Dann können Sie in Ihrem Client-Code während des Kontrollflusses Anweisungen mit dem Effekt "Wenn das zurückgegebene Objekt null ist, diesen Abschnitt überspringen" hinzufügen.

Denken Sie daran, alle Objekte erben von 'Objekt'. Diese stark typisierten Rückgabeobjekte in Ihrer Schnittstelle können auch als 'Objekt' zurückgegeben werden. Das bedeutet, dass jedes stark typisierte Objekt auf null gesetzt werden kann. Wiederholen: Versuchen Sie, einen Nullwert für Methoden mit stark typisierten Rückgabewerten zurückzugeben, und behandeln Sie den Nullwert in Ihrem Client-Code.Wenn die Interface-Methode keine Rückgabe zurückgibt - sie wird als ungültig markiert - müssen Sie sich nicht darum kümmern, in Ihrem Client-Code auf Null zu prüfen, und Sie brauchen auch keine NIE: Die Methode kann leer bleiben und wenn sie aufgerufen wird, tut sie nichts . Wenn Sie darüber nachdenken, können Sie nach einem Interface-Design streben, das keine stark typisierten Rückgabewerte verwendet. Und das geht zu Jamiecs Kommentar: Wir müssen mehr über die Schnittstelle wissen.

+0

Also verwende ich meine Schnittstelle richtig? Und ich muss nur anders mit den NIE umgehen? Es scheint, als ob derselbe Geruch besser gehandhabt wird als das Programm zu stürzen. – user3281977

+0

Nein, es ist nicht der gleiche Geruch. Stellen Sie sich eine Schnittstelle vor, IDriveCar. Und Sie haben zwei Autos: AutomaticCar und StandardCar. Beide werden IDriveCar implementieren. Stellen wir uns vor, sie implementieren beide die Methode ShiftGears(); aber das automatische Auto wird "nichts tun" mit seiner Umsetzungsmethode von ShiftGears() .... nach all seinem ein automatisches Auto. Das StandardCar wird es implementieren mit "benutzen Sie Hand, um Gangschalthebel zum nächsten Gang zu bewegen" und der AutomaticCar wird es mit "nichts tun" umsetzen - was es nicht tun wird, ist eine NIE zu werfen und das Auto zu stürzen! – sapbucket

+0

OK. Ich bekomme das Stück. Aber wenn Sie ein neues Auto (Auto oder Standard) deklarieren, deklarieren Sie ein neues IDriveCar? Oder deklarieren Sie neue AutomaticCar, die gezwungen wurde, ShiftGears() zu implementieren, weil ich Auto fahre. – user3281977

Verwandte Themen