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
Oop 在使用组合时,如何避免子类回调?_Oop_Inheritance_Delegates_Event Listener_Composition - Fatal编程技术网

Oop 在使用组合时,如何避免子类回调?

Oop 在使用组合时,如何避免子类回调?,oop,inheritance,delegates,event-listener,composition,Oop,Inheritance,Delegates,Event Listener,Composition,所以我倾向于选择组合而不是继承,我希望这个问题的答案是非继承性的 在使用复合时,当超类中有一些代码需要调用子类中的代码时,似乎会出现一些情况。这导致了不可伸缩的继承层次结构,这首先违背了使用组合的目的。下面是C#中问题的演示(尽管这是一个一般的oop问题): 公共接口 { 空分原子(原子); 无效保证金(保证金); } 公共课基础化学:地球化学 { 公共空隙分隔体(原子) { //这里可能有额外的逻辑 对于(int i=0;i

所以我倾向于选择组合而不是继承,我希望这个问题的答案是非继承性的

在使用复合时,当超类中有一些代码需要调用子类中的代码时,似乎会出现一些情况。这导致了不可伸缩的继承层次结构,这首先违背了使用组合的目的。下面是C#中问题的演示(尽管这是一个一般的oop问题):

公共接口
{
空分原子(原子);
无效保证金(保证金);
}
公共课基础化学:地球化学
{
公共空隙分隔体(原子)
{
//这里可能有额外的逻辑
对于(int i=0;i
正如你所看到的,这种设计有一个突出的问题。当调用子类“
SeparateAtom()
方法时,它会执行它自己的一些逻辑,然后将其余逻辑委托给基类,基类将在基类而不是子类上调用
BreakBond()
方法

对此,我可以想到各种各样的解决方案,几乎所有这些方案都有相当大的挫折:

  • 复制并粘贴。在这种情况下,最糟糕的选择是简单地将基类“
    SeparateAtom()
    方法”中的循环(和附加逻辑)复制到子类“one”中。我觉得没有必要解释为什么复制和粘贴不是最佳做法。另一种选择是将循环周围的一些额外逻辑打包到额外的方法中,以便只复制循环。但是,对附加方法的调用仍然是复制的,将内容分解为多个方法可能会破坏封装。例如,如果某些逻辑依赖于
    SeparateAtom()
    的特定上下文,并且如果不熟悉代码的人在上下文之外调用,可能会导致错误数据,该怎么办
  • 倾听或观察基类中的断键事件。这个解决方案对我来说似乎有问题,因为扩展基类功能的方式变得不清楚。例如,在没有先验知识的情况下,如果一个人试图扩展类,他们可能会直观地实现上述设计,并将侦听器解释为可选的,而如果一个人想要扩展断键行为,这实际上是必需的
  • 使基类需要委托。例如,基类可能需要对
    IBondBreakDelegate
    的引用,该引用在
    BondBreak()中调用。这与listener方法有一个类似的问题,即组合和其他方法的混合使得基类的预期用途不明确。此外,即使现在有一个实际需要的委托,从而使预期用途更清楚一些,基类现在也不再能够独立工作。此外,如果需要使用附加的子类(例如
    公共类MoreRealisticChemistry
    等)来扩展层次结构,如何通过组合来扩展委托行为
  • 委托一切,而不是组合。我不想走这条路,因为当类需要额外的功能时,所需的委托数量会增加(或者委托中的方法数量会增加)。另外,如果某些委托行为是可选的,该怎么办?然后,要么子类实现的每个行为都需要有单独的可选委托,要么子类中有大量的空方法体
一般来说,当我致力于某种类型的设计时,我会全心全意地去做。当然,在现实世界中有很多警告。但我觉得这件事一定很普遍,有人可能知道一个很好的解决办法。有什么想法吗?

(由于声誉不好,我无法添加评论,但我想指出两点。)

首先,您的代码没有编译,因为这些类没有实现
ICHERIC

第二,“重组合轻继承”只是一个指导方针,并不是盲目地应用。如果解决方案所考虑的模型需要继承或组合,则应选择组合

对于这个特殊的问题,继承(或者更确切地说,专业化)是更明智的方法

public interface IChemistry
{
    void SeparateAtom(Atom atom);
    void BreakBond(Bond bond);
}

public class BaseChemistry : IChemistry
{
    public void SeparateAtom(Atom atom)
    {
        //possible extra logic here
        for(int i=0;i < atom.BondCount;i++)
        {
            //maybe extra logic here etc.
            BreakBond(atom.Bonds[i]);
        }
    }

    public void BreakBond(Bond bond)
    {
        //do some bond breaking logic here
    }
}

public class RealisticChemistry : IChemistry
{
    private BaseChemistry base;

    public RealisticChemistry(BaseChemistry base)
    {
        this.base = base;
    }
    public void SeparateAtom(Atom atom)
    {
        //subclass specific logic here perhaps
        base.SeparateAtom(atom);
    }

    public void BreakBond(Bond bond)
    {
        //more subclass specific logic
        base.BreakBond(bond);
    }
}