C# 派生类中引入的公共接口
两个类,C# 派生类中引入的公共接口,c#,oop,inheritance,downcast,C#,Oop,Inheritance,Downcast,两个类,D1和D2派生自抽象基类B。它们中的每一个共享在B中声明的公共接口,但它们中的每一个也可能有自己的特定公共接口(例如D2具有D2.Bar(),这仅对D2对象有意义): 我在单个集合中混合使用派生对象(例如列表),因为有时我必须对集合中的所有对象调用公共(继承)方法,但有时我只想对D2对象调用Bar(): var list = new List<B>(); list.Add(new D1()); list.Add(new D2()
D1
和D2
派生自抽象基类B
。它们中的每一个共享在B
中声明的公共接口,但它们中的每一个也可能有自己的特定公共接口(例如D2
具有D2.Bar()
,这仅对D2
对象有意义):
我在单个集合中混合使用派生对象(例如列表),因为有时我必须对集合中的所有对象调用公共(继承)方法,但有时我只想对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();
var list=newlist();
添加(新的D1());
添加(新的D2());
foreach(列表中的变量b)
如果(b是D2)
(b)如D2.Bar();
我感觉到代码的味道。降级是个坏主意,基于类型检查做出决策是个坏主意。如果我将
Bar()
移动到基类,那么在D1
对象上调用它是没有意义的(D1.Bar()的D1.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();
现在这是一个有点奇怪的需求,但如果它是一个需求,我认为以一种简单的方式实现它是合理的,而不是为在基类上没有意义的操作添加任何操作实现
不过,我的做法略有不同:
foreach (var d2 in list.OfType<D2>())
{
d2.Bar();
}
foreach(list.OfType()中的变量d2)
{
d2.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();
现在这是一个有点奇怪的需求,但如果它是一个需求,我认为以一种简单的方式实现它是合理的,而不是为在基类上没有意义的操作添加任何操作实现
不过,我的做法略有不同:
foreach (var d2 in list.OfType<D2>())
{
d2.Bar();
}
foreach(list.OfType()中的变量d2)
{
d2.Bar();
}
这正是你的意思:)似乎D2为B添加了比最初定义的更多的行为。这表明存在违规行为(D2正在做不止一件事)。悲观情绪还表明,将D1和D2放在同一个列表中并不一定有意义。那么,也许“是一种”关系在这里不合适?我会尝试切换到composition,并为D1和D2使用一组精确定义的接口,参见。那么D1和D2可能会混合在一个列表中,但前提是您对一个特定行为(接口)感兴趣,而对于另一个接口,您在列表中只有D2(不知道也不关心它)。似乎D2向B添加的行为比最初定义的要多。这表明存在违规行为(D2正在做不止一件事)。悲观情绪还表明,将D1和D2放在同一个列表中并不一定有意义。那么,也许“是一种”关系在这里不合适?我会尝试切换到composition,并为D1和D2使用一组精确定义的接口,参见。然后,D1和D2可能会混合在一个列表中,但前提是您对一个特定行为(接口)感兴趣,而对于另一个接口,您在列表中只有D2(不知道也不关心它)。
B
过去是表示实体的两种逻辑类型的大型类。两种类型都共享一些功能,但有些功能只适用于一种或另一种类型,所以我决定将B
分为几个子类。@BojanKomazec:好的。。。好吧,这样分离列表似乎至少有可能是合理的。看起来不错,但这并不能避免作者所担心的——它与原始代码一样,只是以伪装的方式执行“如果特定子类型,则向下转换”逻辑。@BartoszKP:我从未建议它做任何其他事情。我不认为它“掩饰”了它——它只是更清晰地表达了它,依我看。我在回答中明确地说,我认为有时候做这种事情是可以的,当它简单地表达了需求的时候。是的,你是对的,你已经清楚地指出了这一点。我不同意这是一种表达这种需求的好方法,但在这个抽象层次上,这可能是一个非常主观的问题:)B
过去是一个表示实体的两种逻辑类型的大型类。两种类型都共享一些功能,但有些功能只适用于一种或另一种类型,所以我决定将B
分为几个子类。@BojanKomazec:好的。。。好吧,这样分离列表似乎至少有可能是合理的。看起来不错,但这并不能避免作者所担心的——它与原始代码一样,只是以伪装的方式执行“如果特定子类型,则向下转换”逻辑。@BartoszKP:我从未建议它做任何其他事情。我不认为它“掩饰”了它——它只是更清晰地表达了它,依我看。我在回答中明确地说,我认为有时候做这种事情是可以的,当它简单地表达了需求的时候。是的,你是对的,你已经清楚地指出了这一点。我不认为这是表达这一需求的好方法,但在这个抽象层次上,这可能是一个非常主观的问题:)