如何将方法的返回类型声明为传递给方法的数组中最后一个lambda的返回类型 [英] How to declare method's return type the as return type of last lambda in array passed to the method

查看:112
本文介绍了如何将方法的返回类型声明为传递给方法的数组中最后一个lambda的返回类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要求一些我看不到的东西,如果是的话,我会删除问题。

I ask for something which I see impossible and I'll delete question if it is.

我有方法:

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 方法。

Abstract methods in those interfaces return values of different types. I pass lambdas to my convertBy method.

我想设置 convertBy 返回类型与返回类型 functions [functions.length - 1] 相同。

I would like to set convertBy return type the same as return type of functions[functions.length - 1].

这可能吗?

编辑:

我已经更改了方法的签名和界面内方法的签名。它的工作原理,但前提是我在下面的主要标记位置进行投射。它只需要在4个方法的调用中调用3个怪异的东西,我想在主要版本中完全摆脱强制转换。

I've changed the signature of the method and the signature of the methods inside the interface. It works but only if I do cast in the marked places in the main posted below. The weird things it needs cast only in 3 out of 4 method's invocations, I would like to get rid of casts at all in the main.

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> extends Function<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, flines, join, collectInts);//works without cast!

我不知道理解编译器理解为什么 sum 返回,但不推断实例 collectInts 返回的内容。

I don't understand why compiler understands what sum returns but don't infer what for instance collectInts returns.

推荐答案

看来,你对泛型类型层次结构有一些误解。当你想扩展泛型类型时,你必须对实际做出一个基本的决定。 Ť扩展类或接口的ypes。您可以指定确切类型,例如

It seems, you have some misunderstanding about generic type hierarchies. When you want to extend a generic type, you have to make a fundamental decision about the actual types of the extended class or interface. You may specify exact types like in

interface StringTransformer extends Function<String,String> {}

(这里我们创建一个扩展泛型类型但不是通用类型的类型)

(here we create a type that extends a generic type but is not generic itself)

或者您可以创建一个泛型类型,它使用自己的类型参数来指定超类的实际类型参数:

or you can create a generic type which uses its own type parameter for specifying the actual type argument of the super class:

interface NumberFunc<N extends Number> extends Function<N,N> {}

注意,我们如何创建新的类型参数 N 有自己的约束并使用它来参数化超类以要求它的类型参数匹配我们的。

Note, how we create a new type parameter N with its own constraints and use it to parametrize the superclass to require its type parameters to match ours.

相反,当你声明一个像

In contrast, when you declare a class like

interface FLines<T, R> extends Function

您正在扩展原始类型函数并创建新的类型参数< T,R> 在您的方案中完全没用。

you are extending the raw type Function and create new type parameters <T, R> which are entirely useless in your scenario.

要保留上述示例,您可以将它们实现为

To stay at the above examples, you may implement them as

StringTransformer reverse = s -> new StringBuilder(s).reverse().toString();
NumberFunc<Integer> dbl = i -> i*2;

由于它们继承了正确类型的方法,您可以使用它们来组合这些函数:

and since they inherit properly typed methods, you may use these to combine the functions:

Function<String,Integer> f = reverse.andThen(Integer::valueOf).andThen(dbl);
System.out.println(f.apply("1234"));






将此应用于您的方案,您可以定义接口如


Applying this to your scenario, you could define the interfaces like

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 仅接受可能是组合函数的一个函数:

and redesign your InputConverter to accept only one function which may be a combined function:

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);
    }
}

这可以以类型安全的方式使用:

This can be used in a type safe manner:

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)
);

这篇关于如何将方法的返回类型声明为传递给方法的数组中最后一个lambda的返回类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆