我写了一些代码,发现两个类(下面的鱼和哺乳动物)有一个相同的模式,所以我决定用泛型来总结。
问题是,我需要从基类部分复制构造函数。
而且,不能使用新()约束(CS0304)修复这一点,因为构造函数不是默认的(0-参数)。
我写这篇文章是因为我被告知实现ICloneable不是一个好的实践。
public class OneHeart {...}
public class TwoHeart {...}
public class Animal<TyHeart> /* : ICloneable ?*/ {
public Animal(TyHeart heart) {
if(heart==null) throw new ArgumentNullException();
Heart = heart;
}
public Heart { get; set; }
}
public class Fish : Animal<OneHeart> {
public Fish(OneHeart heart) : base(heart) {}
public Fish(Fish fish) : base(fish.Heart) {} // copy ctor but no use?
}
public class Mammal : Animal<TwoHeart> {
public Mammal(TwoHeart heart, Organ lung) : base(heart) {Lungs=lung;}
public Mammal(Mammal mammal) : base(mammal.Heart) {Lungs=mammal.Lung;}
public Organ Lungs {get; set;} // Mammal-only member:)
}
// The Zoo collects animals of only one type:
public class Zoo<TyHeart, TyAnimal> : LinkedList<TyAnimal>
where TyAnimal : Animal<TyHeart> {
public Zoo() : base() {}
public Zoo(Zoo<TyHeart, TyAnimal> srcZoo) {
foreach(var animal in srcZoo) {
// CS0304 compile error:
base.AddLast(new TyAnimal(animal));
}
}
...
}鱼类和哺乳动物是唯一从动物和
我知道它们都实现了复制构造函数。
编辑:不需要深拷贝.
心脏和肺的类型是单一的,在动物/鱼类/哺乳动物之间共享。
发布于 2013-06-26 00:14:07
实现ICloneable的一个问题是存储位置(字段、变量、数组插槽等)。可以使用可变引用类型来封装标识、可变状态、两者或两者都不能,但.NET或其任何语言都不包含任何标准约定,以指示上述任何给定存储位置中的哪个应该封装。
如果字段Foo1封装标识而不是可变状态,那么George.Clone().Foo1应该引用与George.Foo1相同的实例。
如果字段Foo2封装可变状态而不是标识,那么George.Clone().Foo2应该引用初始化为具有与George.Foo2相同状态的新对象。
如果字段Foo3既不封装可变状态,也不封装标识,即仅封装身份以外的不可变状态,则George.Clone().Foo3可以引用George.Foo3、具有相同状态的新对象或任何其他具有相同状态的方便对象。
如果字段Foo4封装了可变状态和标识,则无法使用Clone方法有意义地克隆类型的实例。
如果有不同的存储位置类型来封装身份、可变状态或两者都没有,那么就没有什么深-浅的区别,因为任何引用类型字段或由类型封装的其他存储位置都应该通过递归地应用上述规则来克隆(注意,对于构造正确的对象,这不会导致无休止的递归,因为两个对象不能有意义地封装彼此的可变状态,除非它们中至少有一个也封装了对方的标识)。不幸的是,由于类型系统中没有这样的区别,所以除了实现即席克隆方法之外,没有实际的解决方案,或者实现一种克隆方法,它使用属性来决定它应该做什么,并且对不包括任何特殊指示符的内置.NET类型使用硬编码行为。
发布于 2013-06-25 15:44:53
如果不以不同的方式使用: base (.)来调用默认的基本构造函数在派生构造函数声明中。
您不必实现ICloneable,因为它可能会给您带来麻烦,问题是它是深的还是浅薄的。但是无论如何,您可以遵循克隆模式(只是不同的称呼)。
这里有一个可以引导您使用或不使用ICloneable接口实现克隆工具的资源:如何在可派生类中实现ICloneable接口。
其想法是创建一个受保护的复制构造函数,而不是默认的构造函数。这将使您保留新的()约束,并在需要时仍然为派生类提供克隆基和派生内容的选项。
https://stackoverflow.com/questions/16933836
复制相似问题