Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between SAM and anonymous functions

I have recently stumbled upon SAM (single abstract method) concept in Java.

I program in Scala and to me, they look the same as anonymous functions (or lambdas), however my IntelliJ suggests me to either use SAM or lambdas in different scenarios.

Example 1:

val x = new Function1[Int, Int] { // here usage of lambda is suggested
  override def apply(x: Int): Int = x * 2
}

Here lambda usage is suggested.

Example 2:

val event: EventHandler[ActionEvent] = new EventHandler[ActionEvent]() { // here usage of SAM is suggested
  override def handle(e: ActionEvent): Unit = {
    println("hi")
  }
}

I struggle to see the difference in syntax between an anonymous function and a SAM. Are there any conceptual or functional differences between the two?

like image 879
Shibalicious Avatar asked Jan 24 '23 19:01

Shibalicious


2 Answers

The syntax is almost the same, the difference is the context.

Function are interfaces supported by language, which allows things like combining 2 functions into one function, are supported by collections etc.

Single Abstract Method is any trait or class which has only one method to implement, and so it would be unambiguous to take this method's signature, turn it into function's signature and let the compiler rewrite such function into an anonymous class instance.

Noticeable differences:

  • compiler is only able to rewrite function into SAM when you provide types that would make it obvious that you don't want to have a function there instead
  • SAM won't be extending function interface, so you won't be able to do e.g. sam1 andThen sam2 unless you somehow add these methods there yourself
  • you cannot just take function returned by something and use it as SAM - function syntax has to be used to initialize SAM object, in place it is created

I guess you can think of both of them as the same concept - some trait/class with exactly one abstract method initialized using function syntax - where some FunctionX interface would be the "default" and compiler would inter to it, and some other implementations would require explicit type ascription and be called SAM.

Whether we see SAM as reuse of function syntax, of function as special case of SAM doesn't change the fact that SAM are NOT lambdas/closures/anonymous functions. This name is used only for things intended to be used as functions, that is implementations of function interfaces (Function1, Function2, ..., PartialFunction, etc).

like image 71
Mateusz Kubuszok Avatar answered Jan 30 '23 22:01

Mateusz Kubuszok


The FunctionN types are special in scala, in that an anonymous function is inferred to be of that type automatically. val twice = (x: Int) => x * 2 is inferred to be a Function1[Int, Int], not any other type, unless the expected type is a (different) SAM interface.

If the expected type is a SAM interface -- an interface with a single abstract method -- it will get converted to that type.

like image 20
Martijn Avatar answered Jan 30 '23 21:01

Martijn