首页 文章

派生类中引入的公共接口

提问于
浏览
1

两个类 D1D2 派生自抽象基类 B . 它们中的每一个都共享 B 中声明的公共公共接口,但它们中的每一个都可能有自己的特定公共接口(例如 D2 具有 D2.Bar() ,仅对 D2 对象有意义):

public abstract class B
{
    public int N { get; set; }
    public abstract void Foo();
}

public class D1 : B
{
    public override void Foo()
    {            
    }
}

public class D2 : B
{
    public override void Foo()
    {
    }

    public void Bar()
    {            
    }
}

我将派生对象混合在一个集合中(例如列表),因为有时我必须在集合中的所有对象上调用公共(继承)方法,但有时我只想在 D2 对象上调用 Bar()

var list = new List<B>();
        list.Add(new D1());
        list.Add(new D2());
        foreach(var b in list)
            if(b is D2)
                (b as D2).Bar();

我觉得代码闻到了这里 . 向下倾斜是一个坏主意,根据类型检查做出决定是个坏主意 . 如果我将 Bar() 移动到基类,则在 D1 对象( what would implementation of D1.Bar() contain? )上调用它是没有意义的 . 界面和组合也没有帮助 . 我觉得这是一种非常普遍的情况,我想知道 what's the best practice in this case? How to avoid downcasting but allow calling public methods specific for derived types?

2 回答

  • 5

    听起来对我来说实际上"check and downcast"恰恰适合您的描述:

    有时我想只在D2对象上调用Bar():

    现在这是一个奇怪的要求,但如果它是一个要求,我认为's reasonable to implement it in a straightforward fashion rather than adding no-op implementations for operations which don'在基类上有意义 .

    但是,我会稍微改变一下:

    foreach (var d2 in list.OfType<D2>())
    {
        d2.Bar();
    }
    

    现在这说明你的意思:)

  • 1

    似乎D2正在向B添加比最初定义的更多行为 . 这表明Single Responsibility Principle正在被侵犯(D2正在做多件事) . 垂头丧气也表明将D1和D2保持在同一个列表中并不一定有意义 . 那么,也许"IS A"关系在这里不合适?我尝试切换到合成并使用一组精确定义的D1和D2接口,参考Interface Segregation Principle . 然后可能D1和D2可以在列表中混合,但只有当你对一个特定的行为(接口)感兴趣时,对于另一个接口,你才会在列表中只有D2(不知道它,也不关心它) .

相关问题