【问题标题】:How to invoke parent class method without creating object of it如何调用父类方法而不创建它的对象
【发布时间】:2012-04-16 12:11:03
【问题描述】:

我可以使用 base.virtualParentMethod() 调用父类方法。但是在以下场景中,如何在不创建它的对象的情况下调用父父类中的方法。

 class A
    {
        public virtual void virtualParentMethod()
        {
            Console.WriteLine("A");
        }
    }
    class B : A
    {
        public override void virtualParentMethod()
        {
            Console.WriteLine("B");
        }
    }
    class C : B
    {
        public override void virtualParentMethod()
        {
            //base.virtualParentMethod();
            //This is where I want to invoke the method of A
            //So that out Will be : A
        }
    }

【问题讨论】:

  • 如果你需要这样做,你很可能需要重构它。你的继承模型和你想要的行为似乎不匹配
  • 如果你真的想这样做,也许你应该考虑改变你的设计......

标签: c# .net oop


【解决方案1】:

如果您在父级的非直接子级中需要某些父级功能,那么您应该将该功能移至单独的方法:

class A
{
    public virtual void VirtualParentMethod()
    {
        Foo();
    }

    protected void Foo()
    {
        Console.WriteLine("A");
    }
}
class B : A
{
    public override void VirtualParentMethod()
    {
        Console.WriteLine("B");
    }
}
class C : B
{
    public override void VirtualParentMethod()
    {        
        Foo();
    }
}

更新

同时考虑:

  • 直接从A继承C
  • 改变继承顺序,即BC
  • 将此行为提取到其他对象

【讨论】:

    【解决方案2】:

    您无法使用base 语法选择要运行的派生方法的版本。运行特定方法的唯一方法是在C 内实例化一个可用于该方法的A 版本(基本上,A真实实例)。 p>

    但是我个人不会这样做。这表明您的继承链存在设计问题。

    如果您需要确保C 运行A,为什么不从C 继承A - C : A

    【讨论】:

      【解决方案3】:

      您根本不能,因为这是Virtual Method Table 的本质,所以virtual 关键字及其覆盖。调用方法的地址将从对应的real类型的虚拟方法表中查找。

      【讨论】:

        【解决方案4】:

        你不能。使用 base.MethodName 将始终调用层次结构中最接近的实现,如果不明确声明可以调用的方法,就无法通过它

        还值得注意的是,如果您发现自己处于希望这样做的情况,那么您就有设计缺陷。

        【讨论】:

          【解决方案5】:

          您已经通过创建 C 的实例(如 C : B, B : A)创建了 A 的实例,因此有一种方法可以通过稍作修改来完成此操作。现在,没有说明这是否是一个好主意;

          如果您在派生方法实现上使用“new”关键字而不是 override,那么您可以直接调用方法的基本实现,绕过中间类实现,通过将对象转换为您想要的实现类型像这样使用;

          class A
          {
              public virtual void virtualParentMethod()
              {
                  Console.WriteLine("A");
              }
          }
          class B : A
          {
              public new void virtualParentMethod()
              {
                  Console.WriteLine("B");
              }
          }
          class C : B
          {
              public new void virtualParentMethod()
              {
                  // casting this to A will allow you to call the base class implementation
                  ((A)this).virtualParentMethod();
              }
          }
          

          请注意,如果您进行此更改,则您已经为方法的任何调用者引入了行为更改,具体取决于他们引用对象的方式。如果您尝试在现有的 C.virtualParentMethod 实现中以这种方式进行转换(声明为“覆盖”),您实际上只是在调用该方法本身并将陷入无限循环。

          或者,你可以重新考虑你的班级设计。 :-)

          【讨论】:

            猜你喜欢
            • 2014-12-03
            • 1970-01-01
            • 2022-01-02
            • 1970-01-01
            • 1970-01-01
            • 2012-07-13
            • 2021-10-18
            • 1970-01-01
            相关资源
            最近更新 更多