SCALA Extension methods

 

Now those of us that have used .NET for a while that we can create extension methods, which are highly useful things.

If you have been living under a rock or something for the last 5 years or so, here is what MSDN says about extension methods

Extension methods enable you to “add” methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are a special kind of static method, but they are called as if they were instance methods on the extended type. For client code written in C# and Visual Basic, there is no apparent difference between calling an extension method and the methods that are actually defined in a type.

https://msdn.microsoft.com/en-gb/library/bb383977.aspx

Which we might define something like this in C#

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

The question is, can this be done using Scala?

Turns out there are actually a number of ways to do this in Scala.

Let’s see 2 of the most popular ways, which both make use of a Scala feature called “impllicits”

Implicits

Scala implicits are too big of a topic for me to explain in this post. I would recommend you read the Scala manual to get a better understanding of them

 

Way 1 : Implicit Method And Regular Class

The first way makes use of a implicit method and a regular Scala class, here is the code

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

Which we can use like this

import MyExtensions._

object ClassesDemo {
  def main(args: Array[String]) =
  {


    val theInt = 20
    val theSquaredInt = theInt.square

    System.out.print(s"theSquaredInt = $theSquaredInt")

    System.in.read()

    ()
  }

}


Way 2 : Implicit Class

Since Scala 2.10 it is possible for classes themselves to be implicit, which means we could also write a Scala extension method like this

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

Usage is the same as above

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

http://stackoverflow.com/questions/3119580/scala-equivalent-of-c-s-extension-methods

Which means that the new code would look like this

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

Usage remains the same as before

 

Where Do Implicits Come From

If you are looking at this code and wondering how the compiler finds the implicit code this next part taken from the Scala docs may help solidify the answer to that a bit

When the compiler sees the need for an implicit, either because you are calling a method which does not exist on the object’s class, or because you are calling a method that requires an implicit parameter, it will search for an implicit that will fit the need.

This search obey certain rules that define which implicits are visible and which are not. The following table showing where the compiler will search for implicits was taken from an excellent presentation about implicits by Josh Suereth, which I heartily recommend to anyone wanting to improve their Scala knowledge. It has been complemented since then with feedback and updates.

The implicits available under number 1 below has precedence over the ones under number 2. Other than that, if there are several eligible arguments which match the implicit parameter’s type, a most specific one will be chosen using the rules of static overloading resolution

  1. First look in current scope
    • Implicits defined in current scope
    • Explicit imports
    • Wildcard imports
    • Same scope in other files
  2. Now look at associated types in
    • Companion objects of a type
    • Implicit scope of an argument’s type
    • Implicit scope of type arguments
    • Outer objects for nested types
    • Other dimensions

     

So I hope that has shown you that you can indeed use extension methods in Scala too

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: