是否可以在Java中为具有接口成员变量的类编写复制构造函数?

che*_*erd 9 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){
        // The following line doesn't work because IAnimal (an interface) doesn't 
        // have a copy constructor
        this.pet = new IAnimal(houseIn.pet);
    }
}
Run Code Online (Sandbox Code Playgroud)

我被迫有一个混凝土Animal吗?如果是这样的话,似乎重复使用课程与狗的房子与猫的房子变得错综复杂!

Bri*_*ian 7

您有三种选择之一:

  1. 有一个方法IAnimal可以深度克隆对象(由像DOM这样的库使用Node.cloneNode(boolean))
  2. 在所有实现中创建一个复制构造函数,IAnimal它采用具体类型并在接口契约中作为需求,然后使用反射来访问它
  3. 创建一个手动复制每个实现的复制工厂
  4. 使用实现深克隆你有自己的合同,如无参构造函数,非最终场,第三方库Serializable类等,像列出的在这里

复制方法

对于#1,执行以下操作:

public interface IAnimal {
    IAnimal cloneDeep();
}
Run Code Online (Sandbox Code Playgroud)

在您的具体类型中实现它,然后调用该方法来复制它:

this.pet = pet.cloneDeep();
Run Code Online (Sandbox Code Playgroud)

然后在界面中记录需求,说出以下内容:

此接口的实现必须返回不==属于此实例的对象,并且必须进行深度克隆,以便操作此对象不会导致操作返回的对象,反之亦然.

实现必须遵循此合同才能符合接口,但这不会在编译时强制执行.

复制构造函数

尝试反复访问复制构造函数,然后声明在接口的所有具体实现中都需要复制构造函数,这将成为接口契约的一部分.每个实现将如下所示:

public class Dog implements IAnimal {

    private String name;

    public Dog(Dog dog) {
        this.name = dog.name;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后您只需要一个方法来复制每个实现:

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);
}
Run Code Online (Sandbox Code Playgroud)

你有这个,在你的界面文档中添加一个声明:

此接口的实现必须定义一个复制构造函数,该构造函数接受其类的相同类型或超类型的参数.此构造函数必须对参数进行深层复制,以便操作此对象不会导致操作返回的对象,反之亦然.

同样,这是运行时强制执行的.当构造函数不存在时,copy上面的方法会抛出NoSuchMethodException错误.

复制工厂

这需要IAnimalinstanceof用来决定将它传递给哪个方法,例如:

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());
}
Run Code Online (Sandbox Code Playgroud)

然后copy手动对每种类型的方法进行深度复制.