我正在尝试使用mixin接口为现有接口添加额外功能。例如。我有一个界面过滤
interface Filtering<T, E>{
T filter(Filter<E> f);
}
我可以轻松地将其添加到现有界面:
interface Container<E> extends Filter<Container<E>, E>{
// translated type: Container<E> filter(Filter<E> f);
}
现在,我还希望有一种转换行为,使用语法
将Container<E>
转换为Container<X>
Container<X> transform(Transformer<E,X> transformer)
有什么方法可以将此功能定义为混合界面,以便我可以将Container<E>
转换为Container<X>
,还可以将SomeOtherContainer<E>
转换为SomeOtherContainer<X>
?< / p>
interface Transforming< /* what goes in here? >{
< /* and what goes in here? */ > X transform(Transformer<S,T> transformer);
}
interface Container<E> extends Transforming<Container<E>, /* and in here? */ >{
}
就个人而言,我认为不可能,我认为我需要将转换方法添加到每个目标接口,但我还没有完全失去希望。有人可以帮忙吗?
澄清:Transformer
功能会将各个E
元素转换为X
个元素。我不希望Transformer
从Container<E>
转换为Container<X>
,这将完全没用。
这就是我想用它的方式:
Container<Integer> intVersion = // initialize it
Container<String> hexVersion =
intVersion.transform(new Transformer<Integer,String>(){
public String apply(Integer input){
return Integer.toHexString(input);
}
});
BTW:我知道我可以在番石榴做类似的事情。让我们忽略这个问题的事实,这不是关于功能(我可以轻松实现),而是关于泛型使用。
答案 0 :(得分:1)
不幸的是,Java不允许这样做:
interface Transforming<E, X>
<T> X<T> transform(Transformer<E,T> transformer);
interface Container<E> extends Transforming<E, Container>
即使它确实如此,也不够通俗;我们想要一个函数映射T
到另一个包含T
interface Transforming<E, f>
<T> f(T) transform(Transformer<E,T> transformer);
interface Container<E> extends Transforming<E, {T->Container<T>} >
但足够的幻想。你能做的最好的事情就是在回报类型上非常模糊:
interface Transforming<E>
<X,T> X transform(Transformer<E,T> transformer);
interface Container<E> extends Transforming<E>
注意,我们无法在X和T之间表达任何约束。
现在您的示例代码编译,没有任何警告!!根据作业有一种类型推断,X
被认为是Container<String>
。
一方面,这种推断的类型安全性完全取决于程序员提供正确的目标类型。如果他把Container<Rope>
放在左边,它也会在没有警告的情况下编译。
另一方面,如果Java没有进行这样的推断,那么我们必须返回Object
而不是X
,并对返回对象进行手动转换;手动模型的安全性当然也完全取决于程序员提供正确的目标类型。因此有人争辩说,为什么我们要惩罚自己呢?如果我将A分配给B,当然A是B,请不要强迫我写出来,推断它!
尽管如此,这种推断可能会给不经意的观察者带来虚假的安全感。 是精神上的手动演员,但不是写作。我个人非常关心这个推理规则。这与静态类型的关键在于,即我们想要明确地写下所有类型。
答案 1 :(得分:0)
你可以尝试(我对语法没有完全的信心,但我认为它很接近):
interface Transforming<X> {
<Y> Y transform(Transformer<X, Y> transformer);
}
interface Container<E> extends Transforming<Container<E>> {
}
然后您的Container将具有转换功能。类型Y将根据变换器的实际调用确定,基于Transformer对象传递给变换的Y.
这不会保证Y必然是Container类型,但也许Transformer中的某些东西可以给出限制。