Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 派生类中引入的公共接口_C#_Oop_Inheritance_Downcast - Fatal编程技术网

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:我从未建议它做任何其他事情。我不认为它“掩饰”了它——它只是更清晰地表达了它,依我看。我在回答中明确地说,我认为有时候做这种事情是可以的,当它简单地表达了需求的时候。是的,你是对的,你已经清楚地指出了这一点。我不认为这是表达这一需求的好方法,但在这个抽象层次上,这可能是一个非常主观的问题:)