调用基类构造函数的虚方法 [英] Calling virtual method in base class constructor
问题描述
我知道,从基类的构造函数调用虚方法可能是危险的,因为子类可能不处于有效状态。 (至少在C#)
我的问题是,如果虚拟方法是什么谁初始化对象的状态呢?它是很好的做法,还是应该是两个步骤,首先创建对象,然后加载状态?
第一种选择:(使用构造函数初始化状态)
公共类BaseObject {
公共BaseObject(定义的XElement){
this.LoadState(定义);
} 保护抽象的LoadState(的XElement定义);
}
第二选项:(使用两步法)
公共类BaseObject {
公共无效的LoadState(定义的XElement){
this.LoadStateCore(定义);
} 保护抽象LoadStateCore(的XElement定义);
}
在第一种方法中的code的消费者可以创建并与一个语句初始化对象
//的基类将调用加载状态的虚方法。
ChildObject O =新ChildObject(高清)
在第二种方法,消费者将不得不创建对象,然后加载状态:
ChildObject O =新ChildObject();
o.LoadState(定义);
(这个答案适用于C#和Java,我相信C ++不同的工作在这个问题上。)
在调用构造一个虚拟的方法确实是危险的,但有时也可以用干净的code结束。
我会尽量避免在可能的情况,但没有弯曲设计的非常的。 (例如,后来初始化选项禁止不变性。)如果你的做的使用虚拟方法在构造函数中,将其记录下来的非常的强烈。只要人人参与意识到它在做什么,它不应该造成的太的许多问题。我会尝试,虽然限制了知名度,因为你已经在你的第一个例子完成。
编辑:有一件事是重要的这里是有一个在初始化顺序C#和Java之间的差异。如果你有一个类,如:
公共类儿童:父母
{
私人INT富= 10; 保护覆盖无效ShowFoo()
{
Console.WriteLine(富);
}
}
其中父
构造函数调用 ShowFoo
,在C#中它会显示10 Java中的同等功能的程序将显示0。
I know that calling a virtual method from a base class constructor can be dangerous since the child class might not be in a valid state. (at least in C#)
My question is what if the virtual method is the one who initializes the state of the object ? Is it good practice or should it be a two step process, first to create the object and then to load the state ?
First option: (using the constructor to initialize the state)
public class BaseObject {
public BaseObject(XElement definition) {
this.LoadState(definition);
}
protected abstract LoadState(XElement definition);
}
Second option: (using a two step process)
public class BaseObject {
public void LoadState(XElement definition) {
this.LoadStateCore(definition);
}
protected abstract LoadStateCore(XElement definition);
}
In the first method the consumer of the code can create and initialize the object with one statement:
// The base class will call the virtual method to load the state.
ChildObject o = new ChildObject(definition)
In the second method the consumer will have to create the object and then load the state:
ChildObject o = new ChildObject();
o.LoadState(definition);
(This answer applies to C# and Java. I believe C++ works differently on this matter.)
Calling a virtual method in a constructor is indeed dangerous, but sometimes it can end up with the cleanest code.
I would try to avoid it where possible, but without bending the design hugely. (For instance, the "initialize later" option prohibits immutability.) If you do use a virtual method in the constructor, document it very strongly. So long as everyone involved is aware of what it's doing, it shouldn't cause too many problems. I would try to limit the visibility though, as you've done in your first example.
EDIT: One thing which is important here is that there's a difference between C# and Java in order of initialization. If you have a class such as:
public class Child : Parent
{
private int foo = 10;
protected override void ShowFoo()
{
Console.WriteLine(foo);
}
}
where the Parent
constructor calls ShowFoo
, in C# it will display 10. The equivalent program in Java would display 0.
这篇关于调用基类构造函数的虚方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!