【问题标题】:C# casting to parent still running child methodsC# 强制转换为仍在运行子方法的父级
【发布时间】:2020-01-09 15:20:13
【问题描述】:

当此代码运行时,输出是 "Child running",即使我将其强制转换为 Parent 类?我可能做错了,如果是这样,我怎样才能达到输出“父母运行”的预期结果? Parent instance = new Child(); 必须保持这样。

class Program
{
    class Parent
    {
        public virtual void Run()
        {
            Console.WriteLine("Parent running.");
        }
    }

    class Child : Parent
    {
        public override void Run()
        {
            Console.WriteLine("Child running.");
        }
    }

    static void Main(string[] args)
    {
        Parent instance = new Child();

        (instance as Parent).Run();

        Console.ReadLine();
    }
}

编辑:

注意到如果我从 Parent 类中删除 virtual 关键字并将此方法的 Child 版本标记为 new 它“解决”了问题。

class Program
{
    class Parent
    {
        public void Run()
        {
            Console.WriteLine("Parent running.");
        }
    }

    class Child : Parent
    {
        public new void Run()
        {
            Console.WriteLine("Child running.");
        }
    }

    static void Main(string[] args)
    {
        Parent instance = new Child();

        (instance as Parent).Run();

        Console.ReadLine();
    }
}

【问题讨论】:

  • virtual 方法就是这样工作的,这几乎总是所需的行为。如果您不希望它是虚拟的,可以尝试去掉 virtual 关键字,但这通常是代码异味。
  • 强制转换对象不会改变对象的类型,你的实例仍然是Child,所以会运行child的实现。
  • @JonathonChase 不完全正确。正如 JL 所说,如果省略 virtual 关键字,则不会创建虚拟表,它将使用父实现。
  • 检查this out。我什至可以把你的问题作为那个问题的副本来结束。
  • @Divisadero 是的,您可以插入一个新方法而不是覆盖一个虚拟方法,但尽管进行了强制转换,但实例仍将键入为Child

标签: c# oop inheritance casting


【解决方案1】:

你基本上不能(没有使用反射技巧)。这就是 C# 中继承的工作原理。

除了覆盖 Run 之外,您可以做的是隐藏它:

public class Parent
{
    public void Run() => Console.WriteLine("Parent");
}

public class Child : Parent
{
    public new void Run() => Console.WriteLine("Child");
}

var child = new Child();
child.Run(); // prints "Child"
((Parent)child).Run(); // prints "Parent"

阴影很少是一个好主意,因为当对象根据其变量的类型改变其行为时,它可能会令人困惑。有关阴影的更多信息,请查看 e。 G。 this question.

【讨论】:

  • 仅供参考,我相信公认的术语(至少 MSDN 使用的)是“方法隐藏”而不是“方法隐藏”。
【解决方案2】:
virtual method should not do anything,it's just a contract,what your goal is a bad ideal.

you should do it like this:

public class animal
{
   public virtual void eat()
   {
      //don't do anything
   }
}

public class dog:animal
{
   public override void eat()
   {
     //eat Meat
   }
}

public class sheep:animal
{
   public override void eat()
   {
     //eat grass
   }
}

【讨论】:

  • “虚拟方法不应该做任何事情”?是的,他们这样做;它们提供了一个默认实现,在子类中可能会或可能不会被覆盖。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-29
  • 1970-01-01
  • 2015-10-20
  • 2015-04-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多