C# 更改父(抽象)类中子类的类型
本文关键字:子类 类型 抽象 | 更新日期: 2023-09-27 18:31:33
代码:
abstract class Parent{
void changeChild(){
}
}
class Child1: Parent{
}
class Child2: Parent{
}
//-----
Parent parent = new Child1(); //instantiated as Child1
parent.changeChild(); //change type of this class to Child2
所以父级应该是 Child2 类的实例。
我知道孩子1可以不同于孩子2(更多/更少的字段,方法),但我只想在这个对象上调用构造函数,这是不允许的。
简单
parent = new Child2();
可以完成,但是有大约 10 个子类(正在增长),我想将其移动到父类中
这在 c# 中可能吗?
谢谢
您无法更改现有对象的类型,但可以创建新对象并将其返回。
例:
abstract class Parent{
Parent ChangeChild<T>() where T : Parent {
if (typeof(T) == typeof(Child1)) {
return new Child1(this);
if (typeof(T) == typeof(Child2)) {
return new Child2(this);
} else {
throw new NotImplementedException("Unhandled type");
}
}
}
class Child1: Parent{
public Child1() {} // create
public Child1(Parent source) {} // convert
}
class Child2: Parent{
public Child2() {} // create
public Child2(Parent source) {} // convert
}
Parent parent = new Child1();
parent = parent.ChangeChild<Child2>();
自动映射器可能是你最好的选择。
T changeChild<T>() : Parent{
// change the type here.
}
这样
的东西会起作用吗?
abstract class Parent {
private Parent Proxy;
public void ChangeChild<T>() where T : Parent, new() {
Proxy = new T();
}
}
必须使用 Proxy
对象来调用成员和属性。
好吧,如果你只想要自动调用 ctor 应该足以满足某些要求,例如
class Child1: Child2{
}
class Child2: Parent{
}
因此,您有Child2
构造Child1
时将调用的 ctor。但就你的架构设计而言,这是完全不同的。
如果这不是您要要求的内容,请澄清。
如果需要在运行时更改某个对象的类型,则不适合继承。你应该在这里使用构图。尝试类似策略的东西(如果类Parent
表示某种行为)。
public class Foo
{
// provide default value (or inject it via ctor)
private Parent _parent = new Child1();
public void ChangeChild(Parent parent){
_parent = parent;
}
public void Bar()
{
_parent.DoSomething();
}
}
public abstract class Parent
{
public abstract void DoSomething();
}
public class Child1: Parent
{
public override void DoSomething() { ... }
}
public class Child2: Parent
{
public override void DoSomething() { ... }
}
现在,您可以在运行时更改依赖项的类型:
Foo foo = new Foo(new Child1());
foo.Bar(); // child1 implementation used
foo.ChangeChild(new Child2());
foo.Bar(); // child2 implementation used
你不能
这样做。也许您可以将Parent
创建为包装类
class Parent
{
Parent _child;
public Parent(Parent child)
{
_child = child;
}
public void ChangeChild(Parent child)
{
_child = child;
}
public string AProperty {
get { return _child.AProperty; }
set { _child.AProperty = value; }
}
public int AMethod(int x)
{
return _child.AMethod(x);
}
}
然后
Parent parent = new Parent(new Child1());
parent.AProperty = "hello";
int y = parent.AMethod(55);
parent.ChangeChild(new Child2());
注意:父母不应该了解一个好的OO设计中的特定子项。这确保了您可以在以后(例如Child3
)创建新的子项,而无需更改Parent
。
但是,如果这对您来说不是问题,并且您希望父级自动关心更改子项,则更改或重载构造函数
public Parent()
{
_child = new Child1();
}
并更改或重载ChangeChild
public void ChangeChild()
{
if (_child is Child1) {
_child = new Child2();
} else {
_child = new Child1();
}
}