我有一个接口(让我们称之为FooInterface),我在一个抽象类的子类(我们称之为A,B,C)的各个子类(我们可以称之为X,Y,Z)中实现(让我们称它为酒吧)。但是必须在所有这些方法中编写(复制)相同的方法是浪费的,更重要的是,考虑到它们只是从接口扩展的子类+那些方法。
因此,我决定删除X,Y,Z层,并使FooInterface成为包装Bar-instances的实际类Foo。但我似乎无法找到一个好方法,我的第一个想法是一个通用的包装类:
public abstract class Bar {/*code*/}
public class A extends Bar {/*code*/}
public class B extends Bar {/*code*/}
public class C extends Bar {/*code*/}
/*
* Removed thanks to using the nifty wrapper Foo now!
* I am so happy I decided to do this,
* can't imagine the horrors I would dream of at night if I had
* an extra redundant class for each subclass of Bar like this!
* public class X extends A implements FooInterface {/*implementing FooInterface*/}
* public class Y extends B implements FooInterface {/*implementing FooInterface*/}
* public class Z extends C implements FooInterface {/*implementing FooInterface*/}
*/
public class Foo<T extends Bar> {
private T t;
public Foo() {t = /*code instantiating T*/}
//code implementing the methods from FooInterface
}
然而,这不起作用,因为在java中使用泛型类型时,获取T的实例似乎很难。
我考虑过做类似于将T作为枚举的事情:
public class Foo<T extends BarType> {
public enum BarType { A, B, C; }
private T t;
public Foo() {
switch(T) {
// code instantiating t by using an ugly hard-coded switch-case...
// please don't make me!
}
//code implementing the methods from FooInterface
}
}
但我无法想象如何能够使用这样的枚举。所以在这一点上,我正在认真考虑放弃空构造函数,并按照以下方式做一些事情:
// No longer generic and instead pass type to constructor!
public class Foo {
public enum BarType { A, B, C; }
private T t;
public Foo(Bartype bartype) {
switch(T) {
// code instantiating t by using an ugly hard-coded switch-case...
// please don't make me!
}
//code implementing the methods from FooInterface
}
}
虽然为了避免必须进行硬编码的switch语句,我更倾向于这个版本:
public class Foo<T extends Bar> {
private T t;
// Foo is used as such: 'Foo<T> foo = new Foo<T>(T.class);'
public Foo(Class<T> clazz) throws InstantiationException,
IllegalAccessException {
// why is it customary to spell this with z?
t = clazz.newInstance()
//code implementing the methods from FooInterface
}
}
如何在java中正确制作这样的包装器?我也考虑过其他方法,例如在将工厂传递给构造函数或执行ParameterizedType事物的泛型类中,或者在非泛型中直接将正确类的实例直接传递给构造函数。但所有这些看起来像是一个很大的麻烦而且非常丑陋,我甚至更喜欢带有类似枚举的硬编码开关盒......
编辑: 正如有些人问我为什么不让Bar实现FooInterface,这是因为Bar是一个很好的纯数据结构,而FooInterface的作用是使它有一些对更专业的实现有用的方法。例如,Bar等是正常的列表(所以它可能我甚至不是实现它们的那个),但是我的实现还必须跟踪哪些是很酷的:
public abstract class List; // Bar
public class LinkedList extends List; // A
public class ArrayList extends List // B
public interface CoolLists { // FooInterface
boolean isCool();
void setCool(boolean cool);
}
public class CoolLinkedList extends LinkedList implements CoolList; // X
public class CoolArrayList extends ArrayList implements CoolList; // Y
不,我不是实际重新实现列表,如果我想跟踪'酷列表',我不会在其中存储布尔值而是使用像HashSet这样的东西存储'酷'的:P
答案 0 :(得分:3)
您应该将Class<T>
传递给Supplier<T>
的构造函数,而不是传递Foo
。要获取实例,只需致电t = supplier.get();
即可。这可以防止您不得不处理反射问题。要获得供应商,您可以使用A::new
,B::new
或C::new
。要创建Foo
的实例,您可以调用:
new Foo<A>(A::new);
没有反映,也没有涉及异常处理。
另见this答案。