如何重写从构造函数调用的基类方法

本文关键字:函数调用 基类 类方法 何重写 重写 | 更新日期: 2023-09-27 18:15:53

我可能做错了…

public class BaseClass
{
  public string result { get; set; }
  public BaseClass(){}
  public BaseClass(string x) {
    result = doThing(x);
  }
  public virtual string doThing(string x)
  {
     return x;
  }
}

public class DerivedClass : BaseClass
{
  public DerivedClass(){}
  public DerivedClass(string x):base(x){}
  public override string doThing(string x)
  {
     return "override" + x;
  }
}

我想为一个新的派生类("测试")有一个"overridetest"的结果,但它没有:它调用doThing的基本方法。我错过什么了吗?我是否需要创建一个AbstractClass并使BaseClass和DerivedClass都继承于此,派生类也覆盖方法?

如何重写从构造函数调用的基类方法

问题是您正在构造函数中进行虚拟调用。这里详细介绍了这个问题的机制和可能的解决方案。

简而言之,当您进入基类的构造函数时,尚未构造被覆盖的函数,因此调用基类中的虚函数。

不能从基类访问子类的实例成员。

它调用基类的doThing方法,因为这是基类所关心的唯一可用的doThing方法。如果你想要每个类的实例调用它自己的doThing方法,在你的子类替换:

public DerivedClass(string x):base(x){}

:

public DerivedClass(string x)
{
    doThing(x);
}

从设计的角度来看,您应该始终警惕在构造函数调用期间"做事情"。构造函数的目的仅仅是使类的实例进入有效状态以备将来使用;它不应该试图"做"任何其他事情或有任何其他副作用。如果您的对象构造是一件复杂的事情,您可能希望使用Builder或Factory模式来保护调用代码免受复杂性的影响。

这是因为您的DerivedClass使用基本构造函数,并将result设置为"测试"的base.doThing("test")

所以你可以把DerivedClass改成:

public class DerivedClass : BaseClass
{
  public DerivedClass(){}
  public DerivedClass(string x):base(x)
  {
     result="override"+x; 
     //or as result already be set as x, you can use: result="override" + result;
  }
}

或者如你所说,

需要创建一个AbstractClass,并同时拥有BaseClass和派生类继承从那,派生类也覆盖的方法?