是否可以在Java中为带有接口成员变量的类编写复制构造函数?
如何为具有接口成员变量的类编写副本构造函数 例如:是否可以在Java中为带有接口成员变量的类编写复制构造函数?,java,interface,copy-constructor,member-variables,Java,Interface,Copy Constructor,Member Variables,如何为具有接口成员变量的类编写副本构造函数 例如: public class House{ // IAnimal is an interface IAnimal pet; public House(IAnimal pet){ this.pet = pet; } // my (non-working) attempt at a copy constructor public House(House houseIn){
public class House{
// IAnimal is an interface
IAnimal pet;
public House(IAnimal pet){
this.pet = pet;
}
// my (non-working) attempt at a copy constructor
public House(House houseIn){
// The following line doesn't work because IAnimal (an interface) doesn't
// have a copy constructor
this.pet = new IAnimal(houseIn.pet);
}
}
我是不是被迫要一个具体的
动物
?如果是这样的话,那么将这个类重新用于养狗的房子和养猫的房子似乎变得很复杂 据我所知,在Java中没有与之直接等价的东西
“正确”的方法是使接口自行实现
最简单的方法可能是使用反射。我知道有一个库可以处理任意对象的深度副本,但我现在记不起它的名字了
相关:如果我理解您的问题,因为您不能在接口中指定构造函数,所以您需要在接口中声明一个深度复制方法,并在类中实现它。不能实例化接口。根据您的需要,您可能还希望深入复制
房屋中的任何内容
public interface IAnimal {
...
IAnimal deepCopy();
}
public House(House houseIn){
this.pet = houseIn.pet.deepCopy();
}
当然,问题是,这取决于你如何让自己不做错事。这有点像你并不真的想要一个接口,而是一个抽象类 好的,让我解释一下代码中的一个问题。请注意,当您有一个界面时,您定义的是一种行为,而不是对象(或生物)的抽象或身份,例如动物。在这种情况下,您需要一个抽象类而不是接口。
贝京说。接口上不能有构造函数(请参阅),因此使用这种方式的接口将失败
因此,在这种情况下,我建议使用抽象类:
public class House {
AbstractAnimal pet;
public House(AbstractAnimal pet) {
this.pet = pet;
}
public House(House houseIn) {
this.pet = new AbstractAnimal(houseIn.pet) {
//implement the abstract methods that are required for anonymous class
};
}
private abstract class AbstractAnimal {
//Abstract class attributes
public AbstractAnimal(AbstractAnimal Parent) {
//Constructor code, can also call abstract methods if required
}
//declare Abstract methods if required.
}
您有三种选择之一:
在IAnimal
上有一个方法来深度克隆对象(由诸如DOM接口之类的库使用)
在IAnimal
的所有实现中创建一个复制构造函数,该构造函数采用具体类型,并将其作为接口契约中的一项要求,然后使用反射来访问它
创建一个复制工厂,手动复制每个实现
使用第三方库,该库通过自己的契约为您实现深度克隆,如无参数构造函数、非最终字段、Serializable
类等,如所列
复制方法
对于#1,执行以下操作:
public interface IAnimal {
IAnimal cloneDeep();
}
在具体类型中实现,然后调用该方法复制它:
this.pet = pet.cloneDeep();
然后将需求记录在界面中,并按照以下内容进行说明:
此接口的实现必须将一个非=
的对象返回到此实例,并且必须进行深度克隆,以便对该对象的操作不会导致对返回对象的操作,反之亦然
实现必须遵循此约定才能与接口兼容,但这不会在编译时强制执行
复制构造函数
尝试以反射方式访问副本构造函数,然后声明在接口中的所有具体实现中都需要副本构造函数,这将成为接口契约的一部分。每个实现将如下所示:
public class Dog implements IAnimal {
private String name;
public Dog(Dog dog) {
this.name = dog.name;
}
}
然后,您只需要一个方法来复制每个实现:
public static <A extends IAnimal> A copy(A animal) {
Class<?> animalType = animal.getClass();
// This next line throws a number of checked exceptions you need to catch
return (A) animalType.getConstructor(animalType).newInstance(animal);
}
然后手动在copy
方法中为每种类型执行深度复制。如果需要深度复制,还应在Animal中实现复制构造函数。不能简单地在Animal中实现复制构造函数。在本例中,您有一个接口IAnimal。因此,您需要知道需要实例化哪个具体类。Cloneable
在很多方面都有缺陷,在effectivejava
中,Josh Bloch建议不要使用它。如果你没有那本书,你应该。见:
public static IAnimal copyAnimal(IAnimal animal) {
if (animal instanceof Dog)
return copyDog((Dog) animal);
if (animal instanceof Cat)
return copyCat((Cat) animal);
//...
else
throw new IllegalArgumentException("Could not copy animal of type: "
+ animal.getClass().getName());
}