How did anonymous function implements the trait?

2019-02-20 03:17发布

let's see the code in scala REPL: first, i defined a trait:

trait Service{
  def invoke(name:String):String
}

then i defined an anonymous function:

def serviceImpl:Service = (name)=> s"Your name is $name"

It works fine.

the serviceImpl method returns an anonymous function --- "(name)=> s"Your name is $name"" is just an instance of Function2[String, String] trait.

but as above, how the anonymous function implements the Service trait?

and How scala does this convert?

标签: scala traits
1条回答
三岁会撩人
2楼-- · 2019-02-20 03:21

This is a new feature describe in the release notes of 2.12: http://www.scala-lang.org/news/2.12.0#lambda-syntax-for-sam-types

The Scala 2.12 type checker accepts a function literal as a valid expression for any Single Abstract Method (SAM) type, in addition to the FunctionN types from standard library. This improves the experience of using libraries written for Java 8 from Scala code. Here is a REPL example using java.lang.Runnable:

scala> val r: Runnable = () => println("Run!")
r: Runnable = $$Lambda$1073/754978432@7cf283e1
scala> r.run()
Run!

Note that only lambda expressions are converted to SAM type instances, not arbitrary expressions of FunctionN type:

scala> val f = () => println("Faster!")
scala> val fasterRunnable: Runnable = f
<console>:12: error: type mismatch;
found   : () => Unit
required: Runnable

The language specification has the full list of requirements for SAM conversion.

With the use of default methods, Scala’s built-in FunctionN traits are compiled to SAM interfaces. This allows creating Scala functions from Java using Java’s own lambda syntax:

public class A {
  scala.Function1<String, String> f = s -> s.trim();
}

Specialized function classes are also SAM interfaces and can be found in the package scala.runtime.java8.

Thanks to an improvement in type checking, the parameter type in a lambda expression can be omitted even when the invoked method is overloaded. See #5307 for details. In the following example, the compiler infers parameter type Int for the lambda:

scala> trait MyFun { def apply(x: Int): String }
scala> object T {
    |   def m(f: Int => String) = 0
    |   def m(f: MyFun) = 1
    | }
scala> T.m(x => x.toString)
res0: Int = 0

Note that though both methods are applicable, overloading resolution selects the one with the Function1 argument type, as explained in more detail below.

查看更多
登录 后发表回答