c# - 如何正确地从派生类复制字段?

标签 c# inheritance

我们以下面的类为例:

基类:

public class Spell
{
    public int castRange;

    public Spell Copy()
    {
        Spell spell = new Spell();
        spell.castRange = this.castRange;
        return spell;
    }
}

派生类:

public class ManaSpell : Spell
{
    public int manaCost;

    public new ManaSpell Copy()
    {
        ManaSpell spell = new ManaSpell();
        spell.castRange = this.castRange;
        spell.manaCost = this.manaCost;
        return spell;
    }
}

我不能为 Copy() 方法使用 virtualoverride 因为它们有不同的返回类型,所以我使用关键字。问题从下一节课开始:

public class Unit
{
    public Spell spell;

    public Unit(Spell spell)
    {
        // This will call the Copy method in the base class, even if the 
        // parameter is actually a ManaSpell

        this.spell = spell.Copy();

        // So instead I have to do a check first:

        if (spell is ManaSpell)
        {
            ManaSpell manaSpell = spell as ManaSpell;
            this.spell = manaSpell.Copy();
        }
    }
}

一切正常,但感觉这是一个非常低效的设计,尤其是如果我添加越来越多的 Spell 派生类,更不用说在基类中添加一个字段意味着更改复制方法在所有派生类中也是如此。

有更好的方法吗?

最佳答案

除非你有充分的理由隐藏(这就是new所做的)你的Copy - 基类的实现,你不应该 new 它。

看来您根本不需要它。您实际上想要复制一个 Spell,而不管它的实际类型。因此,让实例解析对 Copy 的调用,这是通过通常的覆盖来完成的:

public class Spell
{
    public int castRange;

    public virtual Spell Copy()
    {
        Spell spell = new Spell();
        spell.castRange = this.castRange;
        return spell;
    }
}
public class ManaSpell : Spell
{
    public int manaCost;

    public override Spell Copy()
    {
        ManaSpell spell = new ManaSpell();
        spell.castRange = this.castRange;
        spell.manaCost = this.manaCost;
        return spell;
    }
}

现在您可以在 Spell 的任何实例上调用 Copy 而无需区分实际类型:

this.Spell = spell.Copy()

如果您有基类实例,这将解析为 Spell 的新实例;如果您有派生类型的实例,则解析为 ManaSpell

关于c# - 如何正确地从派生类复制字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54331521/

相关文章:

c++ - 在 C++ 中使用成员函数 vector 时,有没有办法实现协变返回类型?

c# - 模拟和 NetworkCredential

c# - 将 C++ 函数转换为 C#

java - 对java中 protected 成员的行为感到困惑

c++ - 继承自 std::vector

javascript - Node.js 使用父对象的数据填充子对象(使用 util.inherits 进行继承)

c# - Sendgrid 邮件功能在 .net Framework 4 中不起作用

c# - asp.net "The DefaultButton of ' Panel1 ' must be the ID of a control of type IButtonControl."错误

C# - 缩短函数调用

c# - 继承和 'Curiously Recurring Template Pattern'