Java 双冒号 (::) 运算符在 Scala 中等效

TiN*_*TiN 3 scala vaadin vaadin-flow

我已经看到了一些如何在 Scala 中编写 :: 等价的示例,例如将 System.out::println 传递给函数,但我无法弄清楚如何在 Scala 中编写此 Vaadin Grid 组件:

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

这里的 get 方法是常规的 getter,而不是静态方法。知道如何用 Scala 2(.12) 编写这段代码吗?

编辑:上面的java代码(grid.addColumn(..))调用这个特定的方法:

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

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

Sil*_*olo 6

这取决于方法的形式,在某些情况下,还取决于您使用的 Scala 版本。Scala 3 对方法的工作方式做了一些相当重大的改变,因此某些语法的工作方式有所不同。

假设我们已经得到了这些签名。

def foo(n: Int): Int
def bar(a: Int, b: String): Int
def baz(): Int
def frobnicate: Int
Run Code Online (Sandbox Code Playgroud)

首先,如果您使用的是 Scala 3 并且该方法采用强制参数,那么您可以简单地使用 a.并将该方法作为一等对象获取。所以对于下面的每一种方法,你都可以使用这个技巧。

在这种情况下,myInstance.foo是一个参数的函数,myInstance.bar也是两个参数的函数。即使在 Scala 3 中,也不能将这个技巧用于零参数的函数。

另一方面,如果该方法没有参数,或者如果您使用的是 Scala 2(该语法在最终确定之前就已出现),那么您可以通过放置下划线(不在括号中)将方法转换为对象在它之后。例如,foo _在 Scala 2 和 3 中, 是一个只有一个参数的函数。bar _是一个有两个参数的函数,并且baz _是一个有零个参数的函数。是一种曾经在 Scala 2 中使用的语法,但对于 Scala 3 中声明的没有frobnicate _括号的零参数函数不再适用。在 Scala 3 中,对于此类函数,您必须将它们包装在显式 lambda 中。

您还可以(对于接受一个或多个参数的函数)在参数位置显式放置下划线。有时这更具可读性,并且如果存在不同参数的多个重载,则这是必需的。因此,在 Scala 2 和 3 中,foo(_)是一个参数的函数,而bar(_, _)是两个参数的函数,我们甚至可以部分应用 barbar(0, _)bar(_, "")

总之,假设此答案顶部列出的签名:

代码 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 _. 这适用于所有情况,除了零参数的 Scala 3 函数(声明时不带括号)(即frobnicate在我们的示例中)。对于这些,你需要一个显式的 lambda,如() => obj.frobnicate