问题描述
如果已经回答,我想提前道歉。由于我不知道如何在标题中正确地写出它,因此我可能错过了另一个类似的问题。我看到了this,它很相似,但是我认为它并不完全一样,因为它的目标不是像我将要描述的那样的层次结构。
说我有一个基类和一个基字段,还有一个作用于该字段的方法DoStuff()
class MyContainer
{
MyField field = new MyField();
protected virtual void DoStuff()
{
field.foo1 = "a";
field.foo2 = "b";
}
}
现在,我想扩展MyContainer,并创建MyContainerExt,它还应包含MyField的派生版本(MyFieldExt)。 MyContainerExt会覆盖DoStuff()在MyFieldExt上做一些额外的工作,但我也希望完成基类中的DoStuff():本质上,我想从基类MyContainer中进行“基”操作和初始化,并且在顶部添加可能需要在派生的MyFieldExt上添加新字段/属性的额外初始化。
要补充一点,现在说我想拥有MyContainerExtExt,它具有一个从MyFieldExt(即MyFieldExtExt)派生的字段,我想在父类已经做的事情上做些事情。
说实话,我不知道如何以有条理和无耻的方式解决这个问题。为了给您一个主意,这就是我想要的(如果您可以使用派生类型覆盖属性,而我知道您无法做到):
class MyContainer
{
abstract MyField Foo {get; set; }
protected virtual void DoStuff()
{
Foo.foo1 = "a";
Foo.foo2 = "b";
}
}
class MyContainerExt: MyContainer
{
override MyFieldExt Foo {get; set;} // I kNow,this is not legal
protected override void DoStuff()
{
base.DoStuff(); // The DoStuff() from the base class is applied
Foo.foo3 = "c"; // Potentially,foo3 and foo4 are fields added to MyFieldExt that
Foo.foo4 = "d"; // the base class MyField kNows nothing about
}
}
class MyContainerExtExt: MyContainerExt
{
override MyFieldExtExt Foo {get; set;} // I kNow,this is not legal (again)
protected override void DoStuff()
{
base.DoStuff(); // The DoStuff() from the first derived class (MyContainerExt( is applied
Foo.foo5 = "e"; // Again,foo5 and foo6 are fields added to MyFieldExtExt that
Foo.foo6 = "f"; // the base class MyFieldExt kNows nothing about
}
}
一开始这可能没有意义,但我想拥有一个层次结构,其中每个“继承级别”上可能会有多种变化:
> MyContainer
>> MyContainerExt1,MyContainerExt2...
>>> MyContainerExt1Ext1,MyContainerExt1Ext2,MyContainerExt2Ext1,MyContainerExt2Ext2...
并且我想考虑这些类必须在它们的一个字段上执行的共同因素:MyContainer需要在其MyField-type字段上执行的大多数(如果不是全部的话)将需要由其所有字段完成请注意,MyContainer的子项也具有MyField的派生版本。我还希望它相对容易扩展:我不希望像示例中那样,通过“管理”使此阶梯适用于最多3个继承级别的解决方案。我可能不需要更多,但是我希望将来编写的代码在MyContainerExtExtExtExt ... Ext或任何情况下都可以扩展。
我对结构没有任何固定要求:它可以是基于属性的,也可以是子类必须重新实现的私有字段,等等。我只想要一种相对干净的方法来实现对MyField的派生版本的初始化/工作,而无需将父代的DoStuff()中的所有行复制到子代的DoStuff()方法中(这会破坏继承点)。
万一有人想知道,我需要用它来在高度分层的WPF应用程序(viewmodel == MyContainer,Model == MyField)中构造我的模型和viewmodel,但这不会影响我认为的问题。
顺便说一句,我正在使用.NET 4.5.2,因此欢迎您使用任何新的技巧。
编辑: 最后我得到了与下面的InBetween答案非常相似的东西。这是我在问之前想要的,但它似乎没有放在正确的位置,因此我想仔细检查一下,没有标准/更好的方法。我的最终结构是这样的:
class MyContainer
{
protected MyField Foo {get; set; }
public MyContainer()
{
Foo = new MyField();
}
protected virtual void DoStuff()
{
Foo.foo1 = "a";
Foo.foo2 = "b";
}
}
class MyContainerExt: MyContainer
{
public MyContainerExt()
{
Foo = new FieldExt(); // no need to override anything for this to work
}
protected override void DoStuff()
{
base.DoStuff(); // The DoStuff() from the base class is applied
MyFieldExt foo = (MyFieldExt)Foo; // The cast always works,since Foo is initialized as FieldExt
foo.foo3 = "c"; // Potentially,foo3 and foo4 are fields added to MyFieldExt that
foo.foo4 = "d"; // the base class MyField kNows nothing about
}
}
class MyContainerExtExt: MyContainerExt
{
public MyContainerExtExt()
{
Foo = new FieldExtExt(); // no need to override anything for this to work
}
protected override void DoStuff()
{
base.DoStuff();
MyFieldExtExt foo = (MyFieldExtExt)Foo; // The cast always works,since Foo is initialized as FieldExtExt
Foo.foo5 = "e"; // Again,foo5 and foo6 are fields added to MyFieldExtExt that
Foo.foo6 = "f"; // the base class MyFieldExt kNows nothing about
}
}
解决方法
您可以执行以下操作。给定您的基本类型;
class MyContainer
{
abstract MyField Foo {get; set; }
protected virtual void DoStuff()
{
Foo.foo1 = "a";
Foo.foo2 = "b";
}
}
无需在派生类型中重新声明MyField
,只需将其强制转换为更具体的类型即可:
class MyContainerExt: MyContainer
{
protected override void DoStuff()
{
base.DoStuff();
var specificFoo = Foo as MyFieldExt; //this cast will always succeed
specificFoo.foo3 = "c";
specificFoo.foo4 = "d";
}
}