派生类中引入的公共接口
本文关键字:接口 派生 | 更新日期: 2023-09-27 18:27:59
两个类D1
和D2
派生自抽象基类B
。它们中的每一个共享在B
中声明的公共接口,但它们中的每个也可能具有自己的特定公共接口(例如,D2
具有仅对D2
对象有意义的D2.Bar()
):
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
对象上调用它将没有意义(D1.Bar()
的实现将包含什么?)。界面和组合也没有帮助。我觉得这是一种非常常见的情况,我想知道这种情况下的最佳做法是什么?如何避免下转换,但允许调用特定于派生类型的公共方法
在我看来,根据您的描述,"check and downstast"实际上是恰当的:
有时我只想在D2对象上调用Bar():
现在这是一个有点奇怪的需求,但如果是的需求,我认为以直接的方式实现它是合理的,而不是为基类上没有意义的操作添加无操作实现。
然而,我的做法略有不同:
foreach (var d2 in list.OfType<D2>())
{
d2.Bar();
}
现在这正是你的意思:)
看起来D2向B添加的行为比最初定义的要多。这表明违反了单一责任原则(D2做了不止一件事)。向下转换还表明将D1和D2保持在同一列表中不一定是有意义的。所以,也许"IS A"关系在这里不合适?我会尝试切换到组合,并为D1和D2使用一组精确定义的接口,参考接口分离原则。那么,D1和D2可能会混合在一个列表中,但前提是你对一个特定的行为(接口)感兴趣,而对于另一个接口,你的列表中只有D2(既不知道,也不关心)。