具有泛型的 Java 复制构造函数

2022-09-04 23:26:40

这在以前可能已经被问过一百万次了,但是我在使用有界类型参数的抽象类上编写复制构造函数时遇到了麻烦。我有一些代码看起来像这样:

public abstract class Superclass<T> {
    Set<? extends Variable<T>> vars;

    public abstract Superclass<? extends T> copy();

    class Variable<T> {
        T value;
    }
}

class Foo extends Superclass<Integer> {
    public Foo copy() {
        Foo _newFoo = Foo();
        Set<FooVariable> _newVars = new HashSet<FooVariable>();
        _newVars.addAll(this.vars);
        _newFoo.vars = _newVars;
    }

    class FooVariable extends Variable<Integer> { /* ... */ }
}

class Bar extends Superclass<String> {
    public Bar copy() {
        Bar _newBar = Bar();
        Set<BarVariable> _newVars = new HashSet<BarVariable>();
        _newVars.addAll(this.vars);
        _newBar.vars = _newVars;
    }

    class BarVariable extends Variable<String> { /* ... */ }
}

由于除了变量类型之外,两者的方法都是相同的,因此我希望能够将该代码移动到超类中的具体方法中。但是我无法弄清楚(a)如何让具体方法在a上调用时返回一个实例,如果在a上调用则返回一个实例,并且(b)根据需要用s或s填充集合。copyFooBarpublic Superclass<? extends T> copyFooFooBarBarvarsFooVariableBarVariable

任何人都可以帮忙告诉我我错过了什么吗?谢谢。


答案 1

那这种呢?Superclass

public abstract class Superclass<T> {

    Set<? extends Variable<T>> vars;

    public Superclass<? extends T> copy() {
        Superclass<T> _newSuperclass = this.getNewInstance();
        Set<Variable<T>> _newVars = new HashSet<Variable<T>>();
        _newVars.addAll(this.vars);
        _newSuperclass.vars = _newVars;
        return _newSuperclass;
    }

    public abstract Superclass<T> getNewInstance();

    class Variable<T> {

        T value;
    }
}

关键是你只需要在子类中实现,而不是构造函数。getNewInstance()

所以看起来就像这样:Foo

class Foo extends Superclass<Integer> {

    @Override
    public Superclass<Integer> getNewInstance() {
        return new Foo();
    }

    class FooVariable extends Variable<Integer> { /* ... */ }
}

答案 2

引入第二个泛型类型参数来表示 、 。Variable<T>U

然后,并且满足边界,可以从该方法返回。Foo.FooVariable<T>Bar.BarVariable<T>Ucopy

编辑

我已经更改了代码以将 的实现移动到超类中。它依赖于一种方法(@OndrejBozek已经引入了)。copynewInstance

public abstract class Superclass<T, U extends Variable<T>> {
    Set<U> vars;

    class Variable<T> {
        T value;
    }

    public Superclass<T, U> copy() {
        Superclass<T, U> _newSuperclass = newInstance();
        Set<U> _newVars = new HashSet<U>();
        _newVars.addAll(vars);
        _newSuperclass.vars = _newVars;
       return _newSuperclass;
    }

    public abstract Superclass<T, U> newInstance();
}

class Foo extends Superclass<Integer, Foo.FooVariable> {
    public Foo newInstance() { return new Foo(); }

    class FooVariable extends Variable<Integer> { /* ... */ }
}

class Bar extends Superclass<String, Bar.BarVariable> {
    public Bar newInstance() { return new Bar(); }

    class BarVariable extends Variable<String> { /* ... */ }
}

推荐