gon*_*opp 12 java generics types composition
我正在尝试实现一个隔离对象的一部分的类,并用其他东西替换该部分.对象的一部分可能与对象本身的类型不同.
一个简单的例子是一个类,它接受字符串"--12--",隔离ascii数字,并用下一个自然数替换它.所以,整个序列将是"--12--" -> "12" -> 12 -> 13 -> "13" -> "--13--".
考虑到这一点,我实现了以下内容:
public abstract class Replacer<Outer, Inner>
{
protected abstract Inner decompose(Outer something);
protected abstract Outer compose(Inner something);
protected abstract Inner inner_replace(Inner something);
public Outer replace(Outer something)
{
Inner s = decompose(something);
s = inner_replace(s);
return compose(s);
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我希望能够组成一系列替换器 - 将它们堆叠起来,以便每个人inner_replace使用"较低"的替换器来计算它:
public abstract class ComposableReplacer<Outer, Inner> extends Replacer<Outer, Inner>
{
protected Replacer<Inner, ?> child;
@Override
public Outer replace(Outer something)
{
Inner s = decompose(something);
s = inner_replace(s);
if (child!=null)
s= child.replace(s);
return compose(s);
}
}
Run Code Online (Sandbox Code Playgroud)
所以,到目前为止,这是正常的,但现在我正在尝试编写一个方便的方法来获取几个ComposableReplacers并自动堆叠它们:
public static <I, O> ComposableReplacer<I, O> compose(ComposableReplacer<?, ?>... rs)
{
for (int i=0; i<rs.length-1; i++)
rs[i].child= rs[i+1];
return rs[0];
}
Run Code Online (Sandbox Code Playgroud)
这会失败,因为每个ComposableReplacer的内部类型必须是其子类型的外部类型,并且编译器无法从数组中推断出它ComposableReplacer<?, ?>.
是否可以在java中执行此操作(并且仍具有类型安全性)?
编辑
要清楚,问题是声明一个方法,它采用一个数组ComposableReplacer并堆栈/链接它们,类型安全.
即使支持通用数组,您的代码也会因逻辑错误而失败。数组由相同类型的元素组成,但您想要执行的操作不适用于相同类型的项目。如果您尝试仅使用两个参数而不是可变参数来实现您的方法,这一点就会变得很清楚:
\n\n// won\xe2\x80\x99t work\npublic static <I, O> ComposableReplacer<I, O> compose(\n ComposableReplacer<I, O> rs1, ComposableReplacer<I, O> rs2) {\n rs1.child=rs2;\n return rs1;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n此代码仍然不会\xe2\x80\x99t 编译,因为rs1.child需要 aComposableReplacer<O,?>而不是 aComposableReplacer<I,O>如果您修复此问题,您的方法将变为
public static <I, O> ComposableReplacer<I, O> compose(\n ComposableReplacer<I, O> rs1, ComposableReplacer<O,?> rs2) {\n rs1.child=rs2;\n return rs1;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n现在可以了,但是两个参数的类型不同。如果 Java 有类型安全数组,则必须防止同时包含 aComposableReplacer<I, O>和 a 。ComposableReplacer<O,?>(除非你强制要求O保持I一致。)
为了进一步说明,这里是三个参数的方法:
\n\npublic static <I, O, X> ComposableReplacer<I, O> compose(\n ComposableReplacer<I, O> rs1, ComposableReplacer<O,X> rs2,\n ComposableReplacer<X, ?> rs3) {\n rs1.child=rs2;\n rs2.child=rs3;\n return rs1;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n在这里您可以看到每个参数都有不同的类型,并且您需要一个额外的类型参数,因此使用 \xe2\x80\x9ctype 安全数组\xe2\x80\x9d (读取 a java.util.List)可以 \xe2\x80\x99t 提供这一点。最简单的解决方案是保留两个参数的方法并让调用者多次调用它。或者 n-arg 如果您知道经常需要 n 参数的用例。
| 归档时间: |
|
| 查看次数: |
302 次 |
| 最近记录: |