2017-01-05 124 views
0

我相信这是重复的,但我不确定我在寻找正确的答案。或理解它回答我的问题。 对于1我认为我使用我的界面错误。对于1我打破了固体的规则,并试图清理它。例如IReelWindow。我在那里特定的东西ReelWindowTumble,其他ReelWindows不使用和抛出未实现的错误。我开始把它分解成多个接口,但发现我不再能够访问ReelWindowTumble的功能,即使我为ITumble创建了一个新接口,并且仍然继承了IReelWindow。问题出在功能代码中。实现泛型类型传递

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。这工作正常,因为我只是想通过IReelWindow我想使用ReelWindow。 我不认为这是我的界面的正确用法。如果我使用ICloneable,我不会声明ICloneable的新对象并将其传递。 但我的意图是创建一个通用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,只有在“IReelWindow”通过我不在乎什么类型reelwindow的,该函数将相应地使用它。

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等。这些派生类型中的每一个都应该由客户端对待(如您所记下的)。

让我们假装ReelWindow从接口实现2种方法,ReelWindowTumble从接口实现3种方法,ReelWindowIndependent从接口实现10种方法。该界面最多可以实现10种方法。

使用你的例子的语言,这意味着ReelWindow将有8个方法带有NotImplementedException(NIE),ReelWindowTumble将有7个方法NIE,而ReelWindowIndependent有0个方法NIE。

你的客户端代码如何?那么,为了使所有这些有意义,您的客户端代码应该在使用_reelWindow时调用所有10种接口方法。这也意味着,使用我的例子,ReelWindowIndependent应该可以很好地处理客户端代码,因为它没有NIE方法。

我会说你真正的问题是NIE的。除去这些异常并返回null。然后,在您的客户端代码中,在控制流程期间,您可以添加语句以“如果返回的对象为null,跳过此部分”。请记住,所有的对象都是从'object'继承的。那些强类型的返回对象也可以作为'object'返回。这意味着任何强类型对象都可以设置为null。重复一遍:尝试为强类型返回值的方法返回null值,并在客户端代码中处理null。现在,如果接口方法没有返回 - 它被标记为void - 那么你不需要担心在你的客户端代码中检查null,你也不需要NIE:方法可以留空,当从字面上调用时什么也不做。如果你仔细想想,你可能会争取不使用强类型返回值的接口设计。这就是Jamiec的评论:我们需要更多地了解界面。

+0

所以我正确使用我的界面?我只需要处理NIE的不同呢?看起来就像处理程序崩溃一样,处理得更好。 – user3281977

+0

不,它不是一样的味道。试想一下名为IDriveCar的界面。你有两辆车:AutomaticCar和StandardCar。他们两人将实施IDriveCar。假设他们都实现了标题为ShiftGears()的方法;但自动驾驶汽车将以其实施方法ShiftGears()......“无所事事”......在所有自动汽车之后。 StandardCar将用“用手将变速杆换到下一档”来实现它,而AutomaticCar将以“什么都不做”的方式来实现它 - 它不会做的就是抛出一个NIE并使车撞车! – sapbucket

+0

好的。我得到那件作品。但是当你宣布新车(自动或标准)时,你是否宣布新的IDriveCar?或者你宣布新的AutomaticCar由于我驾驶汽车而被迫实施ShiftGears()。 – user3281977