实现通用类型以传递

时间:2017-01-05 16:32:44

标签: c# generics interface

我确信这是重复但我不确定我正在寻找正确的答案。或者理解它回答了我的问题。 对于1我认为我使用我的界面错了。对于1我打破了SOLID的规则,并试图清理它。例如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'因为我不关心什么类型的卷轴窗口,所以函数会相应地使用它。

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 个答案:

答案 0 :(得分: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。然后,在您的客户端代码中,在控制流程中,您可以添加语句到"如果返回的对象为空,请跳过本节"。

请记住,所有对象都继承自'对象'。您界面中的那些强类型返回对象可以作为' object'返回。太。这意味着任何强类型对象都可以设置为null。重复:尝试为具有强类型返回值的方法返回null值,并在客户端代码中处理null。现在,如果接口方法没有返回 - 它被标记为void - 那么您不必担心在客户端代码中检查null,也不需要NIE:该方法可以留空并且在字面上调用时什么也没做。如果您考虑这一点,您可能会努力寻求不使用强类型返回值的界面设计。这就是Jamiec的评论:我们需要更多地了解界面。