Scala中的Java双冒号(::)运算符

qvtsj1bj  于 2022-11-09  发布在  Scala
关注(0)|答案(1)|浏览(225)

我见过一些如何在Scala中编写::Equvalant的示例,例如将System.out::println传递给一个函数,但我不知道如何在Scala中编写这个Vaadin网格组件:

Grid<Person> grid = new Grid<>(Person.class, false);
grid.addColumn(Person::getFirstName).setHeader("First name");
grid.addColumn(Person::getLastName).setHeader("Last name");

这里的GET方法是常规的Getter方法,而不是静态方法。你知道如何用Scala2(.12)编写这段代码吗?
编辑:上面的Java代码(grid.addColumn(..))调用这个特定的方法:

public Column<T> addColumn(ValueProvider<T, ?> valueProvider) {
        BiFunction<Renderer<T>, String, Column<T>> defaultFactory = getDefaultColumnFactory();
        return addColumn(valueProvider, defaultFactory);
    }

参考:https://github.com/vaadin/flow-components/blob/2f6bce42b67651fd47d202fa83d8359c619fe099/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/Grid.java#L1625

0ejtzxu1

0ejtzxu11#

这取决于方法的形状,在某些情况下,还取决于您正在使用的Scala版本。Scala 3对方法的工作方式做了一些非常重要的更改,因此一些语法的工作方式有所不同。
让我们假设我们已经得到了这些签名。

def foo(n: Int): Int
def bar(a: Int, b: String): Int
def baz(): Int
def frobnicate: Int

首先,如果您使用的是Scala3,并且该方法接受强制参数,则只需使用.并将该方法作为一级对象获取即可。因此,对于以下每种方法,您都可以使用此技巧。
在这种情况下,myInstance.foo是一个参数的函数,而myInstance.bar是两个参数的函数。即使在Scala3中,您也“不能”在零参数函数中使用此技巧。
另一方面,如果方法没有参数,或者如果您使用的是Scala 2(它是在此语法最终确定之前推出的),则可以通过在方法后面加下划线(而不是在括号中)将其转换为对象。例如,foo _在Scala 2和3中都是一个参数的函数。bar _是两个参数的函数,而baz _是零参数的函数。frobnicate _是一种在Scala 2中使用的语法,但对于在Scala 3中声明的括号为零参数的函数,它将不再起作用。在Scala 3中,对于这类函数,您必须将它们 Package 在显式的lambda中。
您还可以(对于接受一个或多个参数的函数)显式地在参数位置放置下划线。有时,这更具可读性,如果存在不同类型的多个重载,则需要这样做。因此,在Scala 2和3中,foo(_)是一个参数的函数,而bar(_, _)是两个参数的函数,我们甚至可以部分应用bar作为bar(0, _)bar(_, "")
总而言之,假设此答案顶部列出的签名:
Code|Scala 2行为|Scala 3行为
-|-|
obj.foo|错误|(Int) -> Int
obj.bar|错误|(Int, String) -> Int
obj.baz|调用baz()|错误
obj.frobnicate|调用frobnicate|调用frobnicate
obj.foo _|(Int) -> Int|(Int) -> Int
obj.bar _|(Int, String) -> Int|(Int, String) -> Int
obj.baz _|() -> Int|() -> Int
obj.frobnicate _|() -> Int|错误
obj.foo(_)|(Int) -> Int|(Int) -> Int
obj.bar(_, _)|(Int, String) -> Int|(Int, String) -> Int
() => obj.baz()|() -> Int|() -> Int
() => obj.frobnicate|() -> Int|() -> Int
因此,如果您希望最大限度地向后兼容,那么最安全的做法是在函数名后面加上一个_,如obj.foo _所示。这将在所有情况下都有效除了零参数的Scala3函数,这些函数声明时不带括号(即本例中的frobnicate)。对于这些,您需要一个显式的lambda,如() => obj.frobnicate

相关问题