之前可能已经被问了一百万次,但是我在使用有界类型参数在抽象类上编写复制构造函数时遇到了麻烦。我有一些看起来像这样的代码:
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> { /* ... */ }
}
由于copy
和Foo
的{{1}}方法除了变量类型之外是相同的,我希望能够将该代码移动到具体的方法中。超类。但我无法弄清楚(a)如果在Bar
和public Superclass<? extends T> copy
实例上调用,如果调用具体Foo
方法返回Foo
实例Bar
和(b)根据需要使用Bar
或vars
填充FooVariable
集。
有人可以帮忙告诉我我错过了什么吗?感谢。
答案 0 :(得分:2)
这种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> { /* ... */ }
}
答案 1 :(得分:0)
引入第二个通用类型参数来表示Variable<T>
,U
。
然后,Foo.FooVariable<T>
和Bar.BarVariable<T>
满足U
的范围,可以从copy
方法返回。
修改强>
我已经更改了代码,将copy
的实现移到了超类中。它依赖于newInstance
方法(由@OndrejBozek引入)。
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> { /* ... */ }
}
答案 2 :(得分:0)
测试了这段代码,它有几个警告,但它可以做你想要的:
public <C extends Superclass<? extends T>> C copy() throws InstantiationException, IllegalAccessException {
C result= (C) this.getClass().newInstance();
HashSet newVars= new HashSet();
newVars.addAll(this.vars);
result.vars= newVars;
return result;
}
一句话:这不是复制构造函数。这只是一种复制方法。构造函数没有返回类型,其名称等于类名。