问题
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 object
s 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