Method References like in Java 8 in Scala

ぐ巨炮叔叔 提交于 2019-12-23 10:48:08

问题


In this Java class:

import java.util.function.*;

public class T {

    public String func(String a) {
        System.out.println("There we go: " + a);
        return a;
        }

    public static void main(String... args) {
        final Supplier<T> c = T::new;
        final BiFunction<T, String, String> f = T::func;

        final T t = c.get();
        final String v = f.apply(t, "something");

        System.out.println(v);
    }

}

I can get a method reference to the constructor of T and to the instance method func.

Is there a way to do the same in scala, i.e. to get

val c: () => T = ??? // default constructor of T as function
val f: (T, String) => String = ??? // instance method func of T as function

without wrapping them like that:

val c: () => T = () => new T
val f: (T, String) => String = (t, arg) => t.func(arg)

i.e. is there a way which is as elegant as the Java 8 way to get constructor and instance method references to obtain scala functions for these things?


回答1:


First, let's have a look at a literal translation of the Java code to Scala:

class T {
  def func(a:String) : String = {
    println(s"There we go: $a")
    a
  }
}
object T {
  def main(args: Array[String]) = {
    val supplier = () => new T
    val f = (t:T) => t.func _

    val t = supplier()
    val v = f(t)("something")
    println(v)
  }
}

In Scala, functions are first class citizens, hence there's no need to have particular constructions for "things that generate", like the Java Supplier, as it's modeled as a function: f: () => T (same thing goes for its counterpart, the Consumer as f: T => ())

We just said that functions are first class citizens, so let's see a version of the above using this paradigm:

object Tfunc {
  // let's remove the println side-effect from a function.
  val func: String => String = a => s"There we go: $a"

  def main(args: Array[String]) = {
    println(func("something"))
  }
}

In Scala, there's no counterpart to obtain a constructor reference, but if the aim is to use a functional approach, Scala objects offer a simple construct to hold functions and do not require to be instantiated.




回答2:


Exactly the way you do in java 8, you can't. For a class constructor I think there's no way to do that, except the way you did.

For functions you can use parameters placeholders which are "cleaner" in my opinion.

var t = new T()
var func = t.func _
func("a")

If you use a case class then you can use the apply method.

case class C(a: String)
var d = C.apply _
d("c")

You can use the apply function for normal classes too, but you have to implement it yourself. For case classes they are implemented automatically.



来源:https://stackoverflow.com/questions/40398971/method-references-like-in-java-8-in-scala

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!