如何解决基于父实例创建子类的实例?
考虑以下类定义:
class A
{
public int Property1 { get; set; }
public int Property2 { get; set; }
}
class B : A // note that B is a subclass of A
{
// B has only one further property
public int OneMoreProperty { get; set; }
}
给定一个 A
实例,我需要创建一个具有相同值的 B
实例。有没有比复制每个属性更好的方法呢?有机会使用 B
是 A
的子类这一事实吗?这是我目前所拥有的,在我看来非常不方便和容易出错:
// Create instance of A
A instanceA = new A();
instanceA.Property1 = 1;
instanceA.Property2 = 2;
// Create instance of B with same
// values as the instance of A
B instanceB = new B();
instanceB.Property1 = instanceA.Property1;
instanceB.Property2 = instanceA.Property2;
instanceB.OneMoreProperty = 5;
解决方法
您已经非常清楚地说明了为什么以“重用”属性为目的的继承通常是错误的选择。
继承意味着 is-a
关系,但您在这里建模的几乎可以肯定是 A 和 B 之间的 has-a
关系。因此 B
应该只持有 A 的一个实例,否定需要将值从 A 复制到 B。
class A
{
public int Property1 { get; set; }
public int Property2 { get; set; }
}
class B
{
public A A{ get; set; }
public int OneMoreProperty { get; set; }
}
然后
// Create instance of A
A instanceA = new A();
instanceA.Property1 = 1;
instanceA.Property2 = 2;
// Create instance of B with same
// values as the instance of A
B instanceB = new B();
instanceB.A = instanceA;
instanceB.OneMoreProperty = 5;
这是一个明显的过度简化,你可能有一个接受 A
的构造函数,并且你可以引入接口,这样你就可以使 A
和 B
在一些对您的域有意义的共享方式。
您还应该考虑对象的不变性,因为对上述示例中 A
实例的更改会影响 B
持有的引用。
正如@Jamiec 提到的,这里的继承关系可能通过组合更好地建模,但如果 B
在语义上是一个 A
,一种方法是添加一个“复制构造函数”:
class A
{
public int Property1 { get; set; }
public int Property2 { get; set; }
public A() { }
public A(A other)
{
Property1 = other.Property1;
Property2 = other.Property2;
}
}
class B : A
{
public int OneMoreProperty { get; set; }
public B() { }
public B(A other) : base(other) { }
}
然后当您创建 B
实例时:
B instanceB = new B(instanceA);
instanceB.OneMoreProperty = 5;
,
我知道您的确切意思,有时由于多一个属性,我们无法转换某些类。这可以使用反射来实现:
static Tout CopyProps<Tin,Tout>(Tin input) where Tout: Tin,new()
{
var result = new Tout();
foreach (var prop in typeof(Tin).GetProperties())
prop.SetValue(result,prop.GetValue(input));
return result;
}
用法是:
var a = new A{...}
var b = CopyProps<A,B>(a);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。