c# - 当成员字段是对象的集合并且也是继承树的一部分时,成员字段中的多态性

标签 c# oop inheritance polymorphism

我无法清楚地表达这个问题,所以我将从一个例子开始:

public class BirdCollector
{
    protected Dictionary<string, Bird> nameToBird_;

    public BirdCollector(Dictionary<string, Bird> nameToBird)
    {
        nameToBird_ = nameToBird;
    }
}

public class ExoticBirdCollector
{
    public ExoticBirdCollector(Dictionary<string, Bird> nameToBird)
    : base(nameToBird)
    { }

    public ExoticBird GetExoticBird(string name)
    {
        Bird bird;
        if(nameToBird_.TryGetValue(name, out bird))
        {
            return (ExoticBird)bird;
        }
        else
        {
            // handle error
            return null;
        }
    }
}

我传入 ExoticBirdCollector 的字典包含全部ExoticBird ,延伸Bird ,但我每次都必须在 GetExoticBird() 中重新类型转换它们。

是否可以将这些转换一次,也许在构造函数中,这样每次我从 nameToBird_ 得到一只鸟时,它都会是 ExoticBird ?编译器没有任何方法知道我正在传递所有 ExoticBirds在 map 中,除了声明一个单独的字典(例如)之外,还有其他方法可以强制执行此操作吗? Dictionary<string, ExoticBird> nameToExoticBird_

我现在正在考虑做的(这似乎不正确)是在 BirdCollector 中创建 nameToBird_ 。 private 而不是 protected,并将其隐藏在 ExoticBirdCollector 中字符串和 ExoticBird 的字典.

我原来的问题已得到解答,但我有一个相关的后续问题。如果我需要 Dictionary<string, ExoticBird>传递到一个接受 Dictionary<string, Bird> 的新类在构造函数中,我怎样才能实现这一点?我怀疑无法进行向下转换,因为对象位于容器内。我可以创建一个新的 Dictionary<string, Bird>并循环 Dictionary<string, ExoticBird>填充它然后传递它,但这看起来像是一个黑客。

最佳答案

使您的基类通用并移动 GetBird 方法

public class BirdCollector<T> where T : Bird
{
    readonly Dictionary<string, T> nameToBird_;

    public BirdCollector(Dictionary<string, T> nameToBird)
    {
        nameToBird_ = nameToBird;
    }

    public T GetBird(string name)
    {
        T bird;

        if (nameToBird_.TryGetValue(name, out bird))
        {
            return bird;
        }

        // handle error
        return null;
    }
}

然后你可以像这样声明它的派生类

public class ExoticBirdCollector : BirdCollector<ExoticBird>
{
    public ExoticBirdCollector(Dictionary<string, ExoticBird> nameToBird)
        : base(nameToBird)
    {
    }
}

关于c# - 当成员字段是对象的集合并且也是继承树的一部分时,成员字段中的多态性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19032010/

相关文章:

c# - 使用 WPF 播放 MIDI 文件并与视觉同步时间

c# - 将 Web 服务分离到更多文件中

c++ - 当按值发送参数时,为什么不调用默认的复制构造函数?

c++ - { 错误之前的预期类名

c++ - 在 C++ 中创建派生抽象类的实例

c# - 如何使用具有特定子目录的通配符扫描目录

c# - 如果一个类需要在方法中需要时创建另一个类的多个实例,则进行依赖注入(inject)

c++ - 具有转换方法的两个类

c++ - 将方法参数类型更改为子类中的派生类

c# - 为什么在使用 .NET Newtonsoft.Json 组件反序列化一些有效的 json 时,我的 POCO 中的所有集合都是空的