Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implicit class vs Implicit conversion to trait

I'm trying to add new functions to existing types (so I can have the IDE auto suggest relevant functions for types I don't have control over, eg Future[Option[A]]). I've explored both implicit classes and implicit conversions to accomplish this and they both seem to offer the same behavior.

Is there any effective difference between using an implicit class:

case class Foo(a: Int)
implicit class EnrichedFoo(foo: Foo) {
  def beep = "boop"
}
Foo(1).beep // "boop"

And using an implicit conversion:

case class Foo(a: Int)
trait Enriched {
  def beep: String
}
implicit def fooToEnriched(foo: Foo) = new Enriched {
  def beep = "boop"
}
Foo(1).beep // "boop"

I suppose one difference here might be that the first example creates a one-off class instead of a trait, but I could easily adapt the implicit class to extend an abstract trait, eg:

case class Foo(a: Int)
trait Enriched {
  def beep: String
}
implicit class EnrichedFoo(foo: Foo) extends Enriched {
  def beep = "boop"
}
Foo(1).beep // "boop"
like image 940
Mark Pierotti Avatar asked Apr 05 '16 16:04

Mark Pierotti


2 Answers

As far as I'd know, they're pretty much exactly the same. The scoping rules also equally apply to both.

In my opinion, I'd use the implicit classes for your kind of situation. They were probably created exactly for something like that.

Implicit conversions, to me, are more appropriate when you already actually have two different kind of classes and want to convert between the two.

You can check out the initial proposal for implicit classes right here. There it says:

A new language construct is proposed to simplify the creation of classes which provide extension methods to another type.

You can even see how it desugars implicit classes. The following:

implicit class RichInt(n: Int) extends Ordered[Int] {
   def min(m: Int): Int = if (n <= m) n else m
   ...
}

will desugar into:

class RichInt(n: Int) extends Ordered[Int] {
  def min(m: Int): Int = if (n <= m) n else m
  ...
}
implicit final def RichInt(n: Int): RichInt = new RichInt(n)
like image 197
Luka Jacobowitz Avatar answered Oct 26 '22 23:10

Luka Jacobowitz


Well to me its a matter of preference. Actually the implicit classes came into being to ease the creation of classes which provide extension methods to another type. Implicit classes add a lot of value to value classes though.

like image 20
Som Bhattacharyya Avatar answered Oct 26 '22 23:10

Som Bhattacharyya