64

In C# you can write:

using System.Numerics;
namespace ExtensionTest {
public static class MyExtensions {
    public static BigInteger Square(this BigInteger n) {
        return n * n;
    }
    static void Main(string[] args) {
        BigInteger two = new BigInteger(2);
        System.Console.WriteLine("The square of 2 is " + two.Square());
    }
}}

How would this simple extension method look like in Scala?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
John
  • 641
  • 1
  • 6
  • 3

5 Answers5

74

The Pimp My Library pattern is the analogous construction:

object MyExtensions {
  implicit def richInt(i: Int) = new {
    def square = i * i
  }
}


object App extends Application {
  import MyExtensions._

  val two = 2
  println("The square of 2 is " + two.square)

}

Per @Daniel Spiewak's comments, this will avoid reflection on method invocation, aiding performance:

object MyExtensions {
  class RichInt(i: Int) {
    def square = i * i
  }
  implicit def richInt(i: Int) = new RichInt(i)
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mitch Blevins
  • 13,186
  • 3
  • 44
  • 32
  • 32
    Warning: by using the `new { ... }` syntax, you're actually causing the compiler to infer a structural type for the `richInt` method, meaning that any invocations of `square` will be done using reflection (a performance killer). It would be better to define a `RichInt` class which defines `square` and is returned from the `richInt` method. – Daniel Spiewak Jun 25 '10 at 16:46
  • 4
    @Support Add `class RichInt(i: Int) { def square = i * i }` to `MyExtensions` and do `new RichInt(i)` on the `richInt` method. – Daniel C. Sobral Jun 25 '10 at 17:26
  • @Daniel, great, I have an answer with your comment. – OscarRyz Jun 25 '10 at 17:45
  • 3
    @Daniel interesting! I did a small test, the version with the structural type is indeed much slower: http://www.scala-notes.org/2010/06/avoid-structural-types-when-pimping-libraries/ – Jesper Jun 26 '10 at 08:01
  • @Jesper You can even get a little less sneaky and do the following: `val a = new { def b() { error("") } }; a.b()`. This way, you can inspect the stack trace. – Daniel Spiewak Jun 27 '10 at 20:00
67

Since version 2.10 of Scala, it is possible to make an entire class eligible for implicit conversion

implicit class RichInt(i: Int) {
  def square = i * i
}

In addition, it is possible to avoid creating an instance of the extension type by having it extend AnyVal

implicit class RichInt(val i: Int) extends AnyVal {
  def square = i * i
}

For more information on implicit classes and AnyVal, limitations and quirks, consult the official documentation:

megri
  • 1,019
  • 8
  • 10
  • Note that case classes **cannot** be annotated with `implicit` keyword, because they have auto-generated companion object. For more information see documentation links provided by @megri. – falconepl Jan 31 '15 at 12:35
10

This would be the code after Daniel's comment.

object MyExtensions {
    class RichInt( i: Int ) {
        def square = i * i
    }
    implicit def richInt( i: Int ) = new RichInt( i )

    def main( args: Array[String] ) {
        println("The square of 2 is: " + 2.square )
    }
}
Community
  • 1
  • 1
OscarRyz
  • 196,001
  • 113
  • 385
  • 569
2

In Scala we use the so-called (by the inventor of the language) Pimp My Library pattern, which is much discussed and pretty easy to find on the Web, if you use a string (not keyword) search.

Randall Schulz
  • 26,420
  • 4
  • 61
  • 81
2

Scala 3 now has extension methods. Functionally it seems similar as expected to C# and Kotlin.

https://dotty.epfl.ch/docs/reference/contextual/extension-methods.html
https://github.com/scala/scala
https://github.com/lampepfl/dotty

A recent (as of this post) pull shows the syntax being simplified. Stable version as of this post is still 2.x. But there is a 3.xRC, and I noticed Jetbrains already supports it in Idea, partially I assume.

GravityWell
  • 1,547
  • 1
  • 18
  • 22