假设我得到了一个抽象类A。在那里,我得到了一些内部类,如下所示:
public abstract class A
{
public InnerOne x;
public InnerTwo y;
public A(){
this.x = new InnerOne();
this.y = new InnerTwo();
}
public class InnerOne
{
public virtual double value(){
return 0;
}
}
public class InnerTwo
{
public virtual double value(){
return 0;
}
}
}
然后我得到了这样的孩子:
public class B: A
{
public B():base(){
}
public class InnerOne: A.InnerOne
{
public override virtual double value(){
return 100;
}
}
public class InnerTwo: A.InnerTwo
{
public override virtual double value(){
return 100;
}
}
}
所以我认为当我像这样调用构造函数时B
我将通过创建它的内部类实例来初始化x
和y
。但实际上它不是那样工作的。当我像这里这样调用vaule
函数时,它会返回零。
A newobject = new B();
var bv1 = B.x.value();
var bv2 = B.y.value();
有没有办法强制B
类初始化它的x
,并通过它的内部类对象(而不是父抽象类的对象(y
字段,而无需重写它的构造函数?
中定义了类,它们仍然是公共的,并且可以在 A 或 B 外部访问它们。它与在 A 或 B 之外定义的类没有什么不同。
想象一下相同的代码,InnerOne
和InnerTwo
在类 A 和 B 之外定义。它将具有相同的上述行为。混淆的根源是误解了内部类的用法。
为了得到 100,在 B 中,您需要将 X 和 Y 变量的实例显式替换为覆盖这些值的实例。除非你这样做,否则你不会得到100。
public class B: A
{
public B():base(){
X = new OverridenInnerOne();
Y = new OverridenInnerTwo();
}
public class OverridenInnerOne: A.InnerOne
{
public override virtual double value(){
return 100;
}
}
public class OverridenInnerTwo: A.InnerTwo
{
public override virtual double value(){
return 100;
}
}
}
这样做,但你必须改变类A
的定义 - 它变得超级毛茸茸的。
以下是A
:
public abstract class A<I1, I2>
where I1 : A<I1, I2>.InnerOne, new()
where I2 : A<I1, I2>.InnerTwo, new()
{
public InnerOne x;
public InnerTwo y;
public A()
{
this.x = new I1();
this.y = new I2();
}
public class InnerOne
{
public virtual double value()
{
return 0;
}
}
public class InnerTwo
{
public virtual double value()
{
return 0;
}
}
}
这是B
:
public class B: A<B.InnerOne, B.InnerTwo>
{
public B():base(){ }
public class InnerOne: A<InnerOne, InnerTwo>.InnerOne
{
public override double value()
{
return 100;
}
}
public class InnerTwo: A<InnerOne, InnerTwo>.InnerTwo
{
public override double value()
{
return 100;
}
}
}
B.x
和B.y
是A.InnerOne
和A.InnerTwo
的实例,因此您看到返回的值为0,因为它们与B.InnerOne
或B.InnerTwo
无关。
以下B
构造函数会将x
和y
分配给返回 100 的 B.InnerOne
和 B.InnerTwo
实例。
public B(){
this.x = new InnerOne();
this.y = new InnerTwo();
}
如果您希望A
以预期的方式工作,则需要从 B
构造函数传递所需的内部类型,并在 A
构造函数中创建它们的实例,如下所示:
public B():base(typeof(InnerOne),typeof(InnerTwo)) { ... }
使用 Activator.CreateInstance
将允许您在 A
的构造函数中创建这些类型。
如果您总是希望以这种方式使用A
Enigmativity 的通用解决方案会更好,或者这种方式允许您为A
使用多个构造函数,以便您可以选择传入不同的类型。
"内部类"方面(嵌入式类定义(在这里只会分散注意力,它没有任何作用。
回答这个问题:不,你不能有这样工作的"虚拟构造函数"。
当然,有很多方法可以获取100
而不是0
作为返回值,但这个问题太人为了,无法提出一个。