繁体   English   中英

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

[英]Subtype polymorphism without adding dependencies to derived classes

设定

假设我有一个树形结构,其节点都派生自抽象类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();
}

所有派生类都包含一种方法,通过该方法可以设置派生类上的一些其他字段。 这些私有字段是计算神奇水果价值所必需的。

例如, 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());
    }
}

还有一个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());
    }
}

问题

首先将FruitNode树设置为“骨架”,而没有设置每个节点上的任何附加信息。

在程序的稍后阶段,我需要在FruitNode树的每个节点上设置其他数据。 水果节点的所有其他数据都来自同一类型的Economy对象。

当前的解决方案是循环遍历树结构中的所有节点,并对节点的FruitType进行switch 然后将该节点强制转换为其相应的派生类。

    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
            }
        }
    }

但这是丑陋的 在我看来,这似乎是子类型多态性的一个很好的用例。 我可以添加一个

    public abstract void SetAdditionalData(Economy economy);

到抽象的FruitType类基类,然后将逻辑委托给每个派生类本身,以进行从Economy所需的任何计算。

但是EconomyFruitType树类的外部依赖关系,不允许我让FruitType类依赖于Economy类,如果我继续使用抽象方法方法,它们显然会变得如此。

我的问题是 ,还有另一种方法可以模拟多态子类型, 而无需在子类中添加对所讨论方法的参数的依赖性吗?


我为可能是人为的例子(我对OOP不太强)道歉,如果有任何不清楚的地方,请告诉我,我将作相应说明。

实现一个名为IFruitNode的接口,所有水果节点都实现该接口。 其方法之一是SetAdditionalFruitTreeData 然后,您的示例Tree<FruitNode>将是Tree<IFruitNode> ,因此您现有的SetAdditionalFruitTreeData只会循环所有节点并调用IFruitNode.SetAdditionalFruitTreeData()方法。 然后, FruitTree类将不依赖于IFruitNode的实现者。

暂无
暂无

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

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