我要求一些我认为不可能的东西,如果是的话,我会删除问题.
我有方法:
public Object convertBy(Function... functions) { }
这些功能是:
interface FLines extends Function { @Override default Object apply(Object t) { return null; }; public List<String> getLines(String fileName); } interface Join extends Function { @Override default Object apply(Object t) { return null; }; public String join(List<String> lines);//lines to join } interface CollectInts extends Function { @Override default Object apply(Object t) { return null; }; public List<Integer> collectInts(String s); } interface Sum<T,R> extends Function<T,R> { @Override default Object apply(Object t) { return null; }; public R sum(T list);//list of Integers }
这些接口中的抽象方法返回不同类型的值.我将lambdas传递给我的convertBy方法.
我想设置convertBy返回类型与函数的返回类型[functions.length – 1]相同.
这有可能吗?
编辑:
我已经改变了方法的签名和界面内方法的签名.它工作,但只有我在主要标记的位置投射在下面.它只需要在4个方法的调用中的3个中投射出奇怪的东西,我想在主要部分中完全摆脱强制转换.
import java.util.List; import java.util.function.Function; public class InputConverter<T> { private T value; public InputConverter(T value) { this.value = value; } public <T,R> R convertBy(Function<T,R> special,Function... functions) { if (functions.length == 0) { FLines flines = (FLines) special; return (R) flines.getLines((value instanceof String) ? (String) value : null); } else if (functions.length == 1) { FLines flines = (FLines) functions[0]; Join join = (Join) special; return (R) join.join(flines.getLines((String) value)); } else if (functions.length == 2) { if (functions[0] instanceof FLines) { FLines flines = (FLines) functions[0]; Join join = (Join) functions[1]; CollectInts collectInts = (CollectInts) special; return (R) collectInts.collectInts(join.join(flines.getLines((String) value))); } else { Join join = (Join) functions[0]; CollectInts collectInts = (CollectInts) functions[1]; Sum sum = (Sum) special; return (R) sum.sum(collectInts.collectInts(join.join((List<String>) value))); } } else { FLines flines = (FLines) functions[0]; Join join = (Join) functions[1]; CollectInts collectInts = (CollectInts) functions[2]; Sum sum = (Sum) special; return (R) sum.sum(collectInts.collectInts(join.join(flines.getLines((String) value)))); } } /* public Integer convertBy(Join join,CollectInts collectInts,Sum sum) { return sum.sum(collectInts.collectInts(join.join((List<String>) value))); }*/ } interface FLines<T,R> extends Function { @Override default Object apply(Object t) { return null; }; public R getLines(T fileName); // public List<String> getLines(String fileName); } interface Join<T,R> extends Function { @Override default Object apply(Object t) { return null; }; public R join(T lines);//lines to join // public String join(List<String> lines);//lines to join } interface CollectInts<T,R> extends Function { @Override default Object apply(Object t) { return null; }; public R collectInts(T t); // public List<Integer> collectInts(String s); } interface Sum<T,R> { @Override default Object apply(Object t) { return null; }; public R sum(T list);//list of Integers }
主要方法:
FLines<String,List<String>> flines .... Join<List<String>,String> join ... CollectInts<String,List<Integer>> collectInts ... Sum<List<Integer>,Integer> sum ... String fname =/* System.getProperty("user.home") + "/*/ "LamComFile.txt"; InputConverter<String> fileConv = new InputConverter<>(fname); List<String> lines = fileConv.convertBy(flines);//cannot cast from Object to List<String> String text = fileConv.convertBy( join,flines);//cannot cast from Object to String List<Integer> ints = fileConv.convertBy(collectInts,flines,join);//cannot cast from Object to List<Integer> Integer sumints = fileConv.convertBy(sum,join,collectInts);//works without cast!
解决方法
看起来,你对泛型类型层次结构有一些误解.如果要扩展泛型类型,则必须对扩展类或接口的实际类型做出基本决策.您可以指定精确类型,例如
interface StringTransformer extends Function<String,String> {}
(这里我们创建一个扩展泛型类型但不是泛型的类型)
或者您可以创建一个泛型类型,它使用自己的类型参数来指定超类的实际类型参数:
interface NumberFunc<N extends Number> extends Function<N,N> {}
注意,我们如何使用自己的约束创建一个新的类型参数N,并使用它来参数化超类以要求其类型参数匹配我们的类型.
相比之下,当你声明一个类时
interface FLines<T,R> extends Function
您正在扩展原始类型函数并创建新类型参数< T,R>在你的场景中完全没用.
要保留上面的示例,您可以将它们实现为
StringTransformer reverse = s -> new StringBuilder(s).reverse().toString(); NumberFunc<Integer> dbl = i -> i*2;
并且由于它们继承了正确类型的方法,您可以使用它们来组合这些函数:
Function<String,Integer> f = reverse.andThen(Integer::valueOf).andThen(dbl); System.out.println(f.apply("1234"));
将此应用于您的场景,您可以定义类似的接口
interface FLines extends Function<String,List<String>> { @Override default List<String> apply(String fileName) { return getLines(fileName); } public List<String> getLines(String fileName); } interface Join extends Function<List<String>,String> { @Override default String apply(List<String> lines) { return join(lines); } public String join(List<String> lines); } interface CollectInts extends Function<String,List<Integer>> { @Override default List<Integer> apply(String s) { return collectInts(s); } public List<Integer> collectInts(String s); } interface Sum extends Function<List<Integer>,Integer> { @Override default Integer apply(List<Integer> list) { return sum(list); } public Integer sum(List<Integer> list); }
并重新设计您的InputConverter只接受一个可能是组合函数的函数:
public class InputConverter<T> { private T value; public InputConverter(T value) { this.value = value; } public <R> R convertBy(Function<? super T,? extends R> f) { return f.apply(value); } }
这可以以类型安全的方式使用:
FLines flines = name -> { try { return Files.readAllLines(Paths.get(name)); } catch(IOException ex) { throw new UncheckedioException(ex); } }; Join join = list -> String.join(",",list); CollectInts collectInts= s -> Arrays.stream(s.split(",")).map(Integer::parseInt).collect(Collectors.toList()); Sum sum = l -> l.stream().reduce(0,Integer::sum); InputConverter<String> fileConv = new InputConverter<>("LamComFile.txt"); List<String> lines = fileConv.convertBy(flines); String text = fileConv.convertBy(flines.andThen(join)); List<Integer> ints = fileConv.convertBy(flines.andThen(join).andThen(collectInts)); Integer sumints = fileConv.convertBy( flines.andThen(join).andThen(collectInts).andThen(sum) );