我如何调用基类的构造函数之后我调用了自己的构造函数?
问题是,基类的构造函数调用了一个抽象方法(在子类中重写),该方法需要访问在子类的构造函数中初始化的变量
x
?
简短的示例代码:
abstract class BaseClass
{
protected string my_string;
protected abstract void DoStuff();
public BaseClass()
{
this.DoStuff();
}
}
class SubClass : BaseClass
{
private TextBox tb;
public SubClass()
: base()
{
this.my_string = "Short sentence.";
}
protected override void DoStuff()
{
// This gets called from base class' constructor
// before sub class' constructor inits my_string
tb.Text = this.my_string;
}
}
编辑:根据答案,这显然是不可能的。一旦创建了
this.DoStuff();
的每个对象,是否有一种自动方法来调用 SubClass
?当然,我可以在子类的构造函数中的所有其他行之后添加 this.DoStuff();
,但是拥有大约 100 个这样的类,感觉很愚蠢。还有其他解决方案,还是应该使用手动解决方案?
你不能。
此外,通常不应在构造函数中调用
virtual
方法。请参阅此答案。
根据您的实际代码而不是您编写的简单示例,您可以将值作为基本构造函数和
DoStuff
方法的参数传递。例如:
abstract class BaseClass
{
private string my_string;
protected abstract void DoStuff(string myString);
public BaseClass(string myString)
{
this.my_string = myString;
this.DoStuff(this.my_string);
}
}
class SubClass : BaseClass
{
private TextBox tb;
public SubClass()
: base("Short sentence.")
{
}
protected override void DoStuff(string myString)
{
tb.Text = myString;
}
}
如果您的实际代码无法实现,那么编写多个
DoStuff()
即可完成这项工作。还要记住密封您的 SubClass
类,这样其他人就无法通过再次修改 DoStuff
方法来引入错误。
我不会在构造函数中调用抽象方法,因为调用该方法的实例的构造函数可能尚未执行
当调用虚拟方法时,直到运行时才会选择执行该方法的实际类型。当构造函数调用虚方法时,调用该方法的实例的构造函数可能尚未执行。 要修复违反此规则的行为,请勿从类型的构造函数中调用类型的虚拟方法。
http://msdn.microsoft.com/en-us/library/ms182331%28v=vs.80%29.aspx
你不能那样做。但是您可以将主类的启动代码放入单独的初始化方法中。然后,您可以在特定构造函数中 > 在构造函数代码之后调用该方法。
是否有理由无法在类的构造函数实际运行之前构造该类?它需要对如何创建派生类承担更大的责任,这可能不是最佳实践,但它似乎有效。
abstract class BaseClass {
protected string my_string;
protected abstract void DoStuff();
public BaseClass() {
this.DoStuff();
}
}
class SubClass: BaseClass {
TextBox tb;
bool Constructed = false;
void Constructor() {
if (!Constructed) {
Constructed = true;
this.my_string = "Short sentence.";
}
}
public SubClass()
: base() {
Constructor();
}
protected override void DoStuff() {
Constructor();
// This gets called from base class' constructor
// before sub class' constructor inits my_string
tb.Text = this.my_string;
}
}
我不知道这在 2013 年是否有效。它适用于 C# v7.2 (2017) 及以上版本。
如果你可以修改你的基类,那么也许是这样的:
public class BaseClass
{
protected string foo;
protected string bar;
protected string baz;
public BaseClass(foo, Func<string, Tuple<string, string>> fn)
{
var (bar, baz) = fn(foo);
this.foo = foo;
this.bar = bar;
this.baz = baz;
}
}
public class SubClass : BaseClass
{
public SubClass()
: base("NonSence", str => new Tuple<string, string>(str.ToUpper(), str.ToLower))
{ }
}
基本上,设置基类来运行子类传递给构造函数的函数。 “预基地”代码就在那里。然后基类处理该函数及其结果。
如果传递的函数是
global static
而不是匿名,并且返回除 Tuple
之外的其他内容,可能是最好的。