2012-04-19 53 views
0

代码:C#变型类

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类的实例。

我明白,Child1可以不同于Child2(更多/更少的字段,方法), 但我只是想调用此对象的构造函数,这是不允许的。

简单

parent = new Child2(); 

可以做,但像10个类(成长),我想这个迁入父类

在C#这是某种程度上可能吗?

感谢

+0

你一定要使用继承该重新考虑。 – 2012-04-19 13:06:12

+0

@JacekGorgoń你是对的,它可以做到没有继承,它更有效,更好,等等。 – Joe 2012-04-19 13:51:40

+0

和其他人在我的项目中强制使用的泛型也有很好的例子。 – Joe 2012-04-19 14:00:56

回答

1

您不能更改现有对象的类型,但可以创建一个新对象并将其返回。

例子:

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>(); 
+0

可以简化这个。首先将'new()'约束添加到'T'。 'Parent ChangeChild ()其中T:Parent,new()'。然后你可以简单地用'new T()'创建一个新的孩子。 – 2012-04-19 12:43:59

+0

@ OlivierJacot-Descombes:是的,这是一个选项,但不能将当前对象发送给构造函数,因此您需要抽象方法来填充对象。 – Guffa 2012-04-19 12:50:31

+0

是的;然而这个方法可以被保护,因此不会影响'Parent'的公共接口。当新的派生类被引入时,父类也不需要改变。 – 2012-04-19 14:41:37

0

好吧,如果你想只是男星被automaticcally叫,应该足以wtrite的东西,像

class Child1: Child2{ 
} 

class Child2: Parent{ 
} 

所以,你必须Child2构造函数时Child1构成,即会被调用。但是,如果你的是完全不同的架构设计。

如果不是问题,请澄清。

+0

谢谢,但这不符合我项目的OOP思维,例如parent = Dog,child1 = Husky,child2 = whatewer类型的狗 – Joe 2012-04-19 12:31:51

0

Automapper可能是你最好的选择。

T changeChild<T>() : Parent{ 
    // change the type here. 
} 
0

会这样的工作?

abstract class Parent { 
    private Parent Proxy; 
    public void ChangeChild<T>() where T : Parent, new() { 
     Proxy = new T(); 
    } 
} 

您必须使用Proxy对象来调用成员和属性。

0

你不能像这样做。也许你可以创建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()); 

注:家长不应该对自己在一个良好的面向对象设计的具体孩子的了解。这可以确保您可以稍后创建新的孩子(如Child3),而无需更改Parent

但是,如果这不是你的问题,你希望家长要改变孩子,然后更改或

public Parent() 
    { 
     _child = new Child1(); 
    } 

重载构造函数自动处理,改变或过载ChangeChild

public void ChangeChild() 
    { 
     if (_child is Child1) { 
      _child = new Child2(); 
     } else { 
      _child = new Child1(); 
     } 
    } 
0

如果您需要在运行时更改某个对象的类型,则不适用于继承。你应该在这里使用组合。尝试类似Strategy(如果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