【问题标题】:Call base function then inherited function调用基函数然后继承函数
【发布时间】:2011-04-14 10:42:14
【问题描述】:

我有一个基类和一个继承基类的类。基类有几个被继承类可以覆盖的虚函数。但是,基类中的虚函数具有必须在调用继承的类覆盖之前运行的代码。有什么方法可以让我先调用基类虚函数,然后再调用继承的类。无需调用 base.function()。

我知道我可以简单地创建两个函数,一个被调用,另一个是虚拟的。但是有没有办法我也可以保持相同的名字?我知道我可能需要改变一些事情。

class myBase
{
    public virtual myFunction()
        { /* must-run code, Called first */ }
}

class myInherited : myBase
{
    public override myFunction()
        { /* don't use base.myFunction();,
        called from base.myFunction(); */ }
}

类似问题here

【问题讨论】:

    标签: c# inheritance


    【解决方案1】:

    C# 不支持自动执行此操作,但是 您可以使用template method pattern 强制执行它。例如,假设您有以下代码:

    abstract class Animal
    {
        public virtual void Speak()
        {
            Console.WriteLine("I'm an animal.");
        }
    }
    
    class Dog : Animal
    {
        public override void Speak()
        {
            base.Speak();
            Console.WriteLine("I'm a dog.");
        }
    }
    

    这里的问题是任何继承自Animal 的类都需要调用base.Speak(); 以确保执行基本行为。您可以通过以下(略有不同)的方法自动执行此操作:

    abstract class Animal
    {
        public void Speak()
        {
            Console.WriteLine("I'm an animal.");
            DoSpeak();
        }
    
        protected abstract void DoSpeak();
    }
    
    class Dog : Animal
    {
        protected override void DoSpeak()
        {
            Console.WriteLine("I'm a dog.");
        }
    }
    

    在这种情况下,客户端仍然只能看到多态的Speak 方法,但Animal.Speak 的行为保证会执行。问题是如果你有进一步的继承(例如class Dachshund : Dog),如果你想保证Dog.Speak被执行,你必须创建另一个抽象方法。

    【讨论】:

      【解决方案2】:

      可在 .NET Framework 中找到的一个常见解决方案是将一个方法拆分为公共方法 XXX 和一个由公共方法调用的受保护的虚拟方法 OnXXX。对于您的示例,它看起来像这样:

      class MyBase
      {
          public void MyMethod()
          {
              // do something
              OnMyMethod();
              // do something
          }
      
          protected virtual void OnMyMethod()
          {
          }
      }
      

      class MyInherited : MyBase
      {
          protected override void OnMyMethod()
          {
              // do something
          }
      }
      

      【讨论】:

      • 有没有一种方法可以做到这一点,而无需在基类中创建两个函数?或者至少让它们具有相同的名称?
      • @Dave:不,没有办法在虚拟方法调用之前或之后神奇地调用重写的基本方法。你必须以某种方式拆分它。 (如果拆分它,除了在受保护方法之前和之后做一些事情之外,您还可以强制覆盖方法调用覆盖的基方法。)
      【解决方案3】:
       public abstract class BaseTemp
      {
          public void printBase() {
              Console.WriteLine("base");
              print();
          }
      
          public abstract void print();
      
      }
      
      public class TempA: BaseTemp
      {
          public override void print()
          {
              Console.WriteLine("TempA");
          }
      }
      
      public class TempB: BaseTemp
      {
          public override void print()
          {
              Console.WriteLine("TempB");
          }
      }
      

      【讨论】:

        【解决方案4】:

        除了你已经命名的 2 种方法之外,没有其他方法可以做你正在寻找的东西。

        要么在基类中创建 2 个函数,一个被调用,另一个为虚拟函数。

        或者你在子类中调用base.functionName。

        【讨论】:

          【解决方案5】:

          不完全是。但我使用抽象方法做了类似的事情。

          抽象方法必须被派生类覆盖。抽象过程是虚拟的,因此您可以确定当基类调用它们时,会调用派生类的版本。然后让你的基类的“必须运行代码”在运行后调用抽象过程。瞧,您的基类代码总是首先运行(确保基类 proc 不再是虚拟的),然后是派生类的代码。

          class myBase
          {
              public /* virtual */ myFunction()  // remove virtual as we always want base class's function called here 
              { /* must-run code, Called first */ 
          
                  // call derived object's code
                  myDerivedMustcallFunction();    
              }
          
              public abstract myDerivedMustCallFunction() { /* abstract functions are blank */ }
          }
          
          class myInherited : myBase
          {
              public override myDerivedMustCallFunction()
              { /* code to be run in derived class here */ }
          }
          

          【讨论】:

          • 抽象方法为什么要公开?
          【解决方案6】:

          你怎么看?

          class myBase
          {
              public void myFunctionWrapper()
              {
                  // do stuff that must happen first
                  // then call overridden function
                  this.myFunction();
              }
          
              public virtual void  myFunction(){ 
                 // default implementation that can be overriden
          
              }
          
          }
          
          class myInherited : myBase
          {
              public override void myFunction()
              { 
          
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-06-06
            • 2011-01-08
            • 2013-03-30
            • 2013-06-01
            • 1970-01-01
            相关资源
            最近更新 更多