我有一个有趣的建筑我正在玩。人们可以制作包含StoredObjects的商店。商店可以支持由界面表示的不同操作(即Get,Put,Print)。
以下是它的外观,高度简化:
interface Put<Foo>{
public void put(Foo f);
}
class Store implements Put<Store.Obj<?>> {
class Obj<T> {
public T o;
}
@Override
public void put(Obj<?> o) { }
}
public class Main {
public static void main(String[] args){
Store s = new Store();
Store.Obj<String> o = s.new Obj<>();
s.put(o);
}
}
当我想实现类似的“get”方法时,问题出现了。理想情况下,我想要一个看起来像这样的界面:
interface Get<Foo> {
public <T> T get(Foo<T> f);
}
显然,这是畸形的java。是否有一些语法(或黑客)可以用来实现这意味着什么?实际上,我不想将常量类型指定为泛型参数,而是将可参数化类型指定为泛型参数(然后将在get方法中对其进行参数化)。是的,这归结为更高级的类型,java没有;如此疯狂 - 丑陋的黑客不仅仅是欢迎!
由于其他设计限制而无效的常见解决方案:
Obj
类Store.Obj<T>
的超类型并指定接受它的接口,而不是通用参数。答案 0 :(得分:0)
你需要一些方法让你的Obj离开。我们称之为 Getter 。
interface Getter<O, I> {
I get(O outer); // get the "inner" value out of the "outer" object
}
现在,您可以为Obj
类实现一个getter:
class ObjTGetter<T> implements Getter<Obj<T>, T> {
public T get(Obj<T> o) { return o.o; }
}
现在,您的Store
构造函数还必须包含Getter
参数,因此您可以使用它来实现get。您的商店类将成为:
class Store<O, I> implements Put<O>, Get<O, I> {
private Getter<O, I> getter;
public void put(O o) { … }
public I get(O o) { … }
}
但到那时你也可以摆脱你的Store
并直接使用getter。
答案 1 :(得分:0)
我想我们可以从一开始就忘记高等级的类型,你知道你的建议是不可能的。
这不是你可能想要的解决方案,但这是我在这个问题上的最佳答案。
由于我们无法创建新的参数类型,因此我们不得不求助于创建新的参数值。
首先,我们必须声明Foo
是通用类型。事实上,Java 8中有一种更好的类型:Supplier<T>
interface Supplier<T> {
T get()
}
现在,让我说我必须使用这种类型的值:
Supplier<String> s = () -> "Hello";
Supplier<Integer> i = () -> 42;
好吧,既然我们没有更高级的kinded类型,那么我们的Get
接口必须在编译时与一些泛型类型相结合:
interface Get<S, F extends Supplier<S>> {
public S get(Supplier<S> foo);
}
问题显然是,对于Get
的每个可能类型T,您需要Supplier<T>
的多个实例/值,因此我们有了大量的值:
Get<String, Supplier<String>> f = Supplier::get;
Get<Integer, Supplier<Integer>> g = Supplier::get;
然后我们就可以了
String m = f.get(); //yield "Hello"
Integer n = g.get(); //yields 42
供应商几乎可以包含您想要的任何内容,但我认为我们不能逃避定义多个Get实例。