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
First look in current scope
- Implicits defined in current scope
- Explicit imports
- Wildcard imports
- Same scope in other files
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