简体   繁体   English

子类型多态性,不向派生类添加依赖项

[英]Subtype polymorphism without adding dependencies to derived classes

Setup 设定

Suppose I have a tree structure with nodes all deriving from abstract class FruitNode . 假设我有一个树形结构,其节点都派生自抽象类FruitNode

public abstract class FruitNode : Tree<FruitNode>
{
    public double NodeId { get; private set; }

    public FruitType Type { get; private set; }

    protected FruitNode(double nodeId, FruitType fruitType)
    {
        NodeId = nodeId;
        Type = fruitType;
    }

    public abstract double GetMagicalFruitValue();
}

All derived classes contain a method with which some additional fields on the derived class are set. 所有派生类都包含一种方法,通过该方法可以设置派生类上的一些其他字段。 These private fields are required to compute the magical fruit value. 这些私有字段是计算神奇水果价值所必需的。

For instance, a Banana derived class may look like this. 例如, Banana派生类可能看起来像这样。

public class Banana : FruitNode
{
    private List<double> _bananaSecretValues;
    public Banana(double id) : base(id, FruitType.Banana) {}

    public void SetAdditionalBananaData2(List<double> computedBananaValues)
    {
        _bananaSecretValues = computedBananaValues;
    }

    public override double GetMagicalFruitValue()
    {
        return Math.Exp(_bananaSecretValues.Sum());
    }
}

And an Orange derived class. 还有一个Orange派生类。

public class Orange : FruitNode
{
    private List<double> _orangeSecretValueList1;
    private List<double> _orangeSecretValueList2; 

    public Orange(double id) : base(id, FruitType.Orange) {}

    public void SetAdditionalOrangeData(List<double> 
        computedList1Values, List<double> computedList2Values)
    {
        _orangeSecretValueList1 = computedList1Values;
        _orangeSecretValueList2 = computedList2Values;
    }

    public override double GetMagicalFruitValue()
    {
        return Math.Cos(_orangeSecretValueList1.Zip(_orangeSecretValueList2,
            (one, two) => one - two).Average());
    }
}

The question 问题

The FruitNode tree is first set as a "skeleton", with none of the additional information on each node being set. 首先将FruitNode树设置为“骨架”,而没有设置每个节点上的任何附加信息。

At some later stage in the program, I need to set the additional data on each node in the FruitNode tree. 在程序的稍后阶段,我需要在FruitNode树的每个节点上设置其他数据。 All of the additional data for the fruit nodes stems from the same object of type Economy . 水果节点的所有其他数据都来自同一类型的Economy对象。

The current solution is to loop over all of the nodes in the tree structure, and implement a switch on what the FruitType of the node is. 当前的解决方案是循环遍历树结构中的所有节点,并对节点的FruitType进行switch The node is then cast to its corresponding derived class. 然后将该节点强制转换为其相应的派生类。

    public void SetAdditionalFruitTreeData(IEnumerable<FruitNode> nodesInFruitTree, Economy economy)
    {
        foreach (var node in nodesInFruitTree)
        {
            switch (node.Type)
            {
                case FruitType.Banana:
                {
                    List<double> computedBananaValues = new List<double>();

                    // do some manipulations with the economy to add values to
                    //    the computed banana values

                    // cast the node to the derived type Banana, and call
                    //    the SetAdditionalBananaData class 

                    break;
                }
                case FruitType.Orange:
                {
                    List<double> computedBananaValues = new List<double>();

                    // do some manipulations with the economy to add values to
                    //    the computed banana values

                    // cast the node to the derived type Orange, and call
                    //    the SetAdditionalOrangeData

                    break;
                }
                // continued for other fruit types
            }
        }
    }

But this is ugly . 但这是丑陋的 To me, this looks like a great use case for subtype polymorphism. 在我看来,这似乎是子类型多态性的一个很好的用例。 I could add a 我可以添加一个

    public abstract void SetAdditionalData(Economy economy);

to the abstract base FruitType class, and then delegate the logic to each derived class itself to proceed with whatever calculations it needs from the Economy . 到抽象的FruitType类基类,然后将逻辑委托给每个派生类本身,以进行从Economy所需的任何计算。

However , Economy is an external dependency from the FruitType tree classes, and I am not permitted to have the FruitType classes become dependent on the Economy class, which they evidently would become if I proceeded with the abstract method approach. 但是EconomyFruitType树类的外部依赖关系,不允许我让FruitType类依赖于Economy类,如果我继续使用抽象方法方法,它们显然会变得如此。

My question is , is there another way in which you can emulate polymorphic subtyping without adding a dependency in the subclasses on the parameters of the method in question? 我的问题是 ,还有另一种方法可以模拟多态子类型, 而无需在子类中添加对所讨论方法的参数的依赖性吗?


My apologies for the possibly contrived example (I'm not very strong with OOP), if anything is unclear please do let me know and I will clarify accordingly. 我为可能是人为的例子(我对OOP不太强)道歉,如果有任何不清楚的地方,请告诉我,我将作相应说明。

Implement an interface called IFruitNode which all fruit nodes implement. 实现一个名为IFruitNode的接口,所有水果节点都实现该接口。 One of its methods would be SetAdditionalFruitTreeData . 其方法之一是SetAdditionalFruitTreeData Your example Tree<FruitNode> would then be Tree<IFruitNode> and thus your existing SetAdditionalFruitTreeData would just loop all node and call the IFruitNode.SetAdditionalFruitTreeData() method. 然后,您的示例Tree<FruitNode>将是Tree<IFruitNode> ,因此您现有的SetAdditionalFruitTreeData只会循环所有节点并调用IFruitNode.SetAdditionalFruitTreeData()方法。 The FruitTree class would then have no dependency on the implementors of IFruitNode . 然后, FruitTree类将不依赖于IFruitNode的实现者。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM