Scala equivalent of C#’s extension methods?

2019-01-30 03:41发布

问题:

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?

回答1:

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)
}


回答2:

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:

  • http://docs.scala-lang.org/overviews/core/implicit-classes.html
  • http://docs.scala-lang.org/overviews/core/value-classes.html


回答3:

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 )
    }
}


回答4:

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.