为什么vavr的Function1不能接受Seq <Parent>类接受Seq <Child>?

问题描述

我将Java与vavr结合使用,并且我具有一个Function1,该函数接受Seq<Parent>并返回String。那个班级为什么不接受Seq<Child>?似乎有些东西具有逆方差/协方差/不变性,但是我很难理解为什么它不能编译。这是我的代码:

interface Bar {
    String getFoo();
}   

class Foo implements Bar {
    private String foo;
    private String bar;

    @Override
    public String getFoo() {
        return foo;
    }

    public Foo(String foo,String bar) {
        this.foo = foo;
        this.bar = bar;
    }
}


class Scratch {
    public static void main(String[] args) {
        Function1<Seq<Bar>,String> myFunction = (it) -> "foo";
        Foo obj = new Foo("foo","bar");
        Foo obj1 = new Foo("hello","world");
        Seq<Foo> list = List.of(obj,obj1);
        String result = myFunction.apply(list); // IntelliJ says this line is incorrect
    }
}

相反,我得到了错误(来自IntelliJ):

    apply (io.vavr.collection.Seq<Bar>) in Function1 cannot be applied to (io.vavr.collection.Seq<Foo>).

这个简单的例子似乎应该可以正常工作。我想念什么,为什么不起作用?

解决方法

我最终弄清楚了。可以归结为Vavr如何通过Seq接口处理方差。

Scala中的

Seq是协变的,这意味着Seq<Child>被视为Seq<Parent>的子类。因此,上述问题在翻译成Scala时有效。

class Bar {}
class Foo extends Bar

val foos: Seq[Foo] = Seq(new Foo,new Foo,new Foo);
val bars: Seq[Bar] = foos;

但是,似乎vavr的Seq接口是不变的,这意味着Seq<Parent>Seq<Child>被视为单独的类。 Vavr的Seq具有一种称为narrow()的方法,可以使这些上行广播正常工作。这就是解决上述问题的方法。

class Scratch {
    public static void main(String[] args) {
        Function1<Seq<Bar>,String> myFunction = (it) -> "foo";
        Foo obj = new Foo("foo","bar");
        Foo obj1 = new Foo("hello","world");
        Seq<Foo> list = List.of(obj,obj1);
        String result = myFunction.apply(Seq.narrow(list));
   

不确定为什么要用这种方式设计Vavr。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...