【发布时间】:2016-02-12 03:22:24
【问题描述】:
此代码显示我想做的事情(但不起作用)。
abstract class Item<I extends Item<I>> {
public abstract void add();
public abstract void test();
public static <T extends Item<T>> Item<T> getZero() {
return T.ZERO();
}
protected static <T extends Item<T>> Item<T> ZERO() {
class ZERO extends Item<T> {
public void add() {}
public void test() { System.out.println("item"); } // don't call this
}
return new ZERO();
}
public static void main(String[] args) {
Item.<Book>getZero().test();
}
}
class Book extends Item<Book> {
public void add() { /* addition implementation goes here */ }
public void test() { System.out.println("book"); } // this should be called
protected static Item<Book> ZERO() { return new Book(); }
}
我想确保当Item.<Book>getZero() 时,它调用Book.ZERO() 而不是Item.ZERO()。但是,由于类型擦除,这不起作用,程序打印item。
我想修改它以使其工作(最好避免使用反射)。这是这样做的目的:
如果我打电话给Arrays.stream(books).collect(Item.<Book>getZero(), Item::add, Item::add);,我希望能够添加所有项目。
为了方便计算(并避免处理Optional<Book>),我想定义一个具体的零对象。但是,由于我希望 Item 的所有实现都是可变的,因此我想确保 Item 的每个子类(例如 book)都有自己的可变实现。 换句话说,ZERO 的默认实现是操作的占位符,不应使用。
我想在不向调用方法传递额外对象的情况下执行此操作(在 Item 的每个实现中都应该固有加法/零方法),并且不需要 Item 对象的实例来创建零对象。这对我很有用,因为我想用 Items 执行操作,只知道它们可以相加和比较,这样我就可以保存 Item 的实现以备后用。
【问题讨论】:
-
为什么你的泛型是自引用的?
-
为什么不能只使用
Book.ZERO()而不是Item.<Book>getZero() -
我从 Java 8 中定义 BaseStream 的方式中获得了这个想法。另外,我想确保我可以调用 Item
book = new Book();因为 Item 对象是我打算使用的对象。 -
@Codebender 的方法几乎和它将会得到的一样好。你不能在 Java 中做你想做的事情,因为你不能有像可覆盖的静态方法这样的东西。
-
@Codebender 调用流的类具有类型参数
>,因此我打算使用 Item. 定义。但是,如果这没有任何帮助,我可以切换。
标签: java generics java-stream reduction abstract-data-type