Over a million developers have joined DZone.
Platinum Partner

Why Scala Doesn’t Have Java Interfaces (And Doesn’t Need Them)

· Java Zone

The Java Zone is brought to you in partnership with ZeroTurnaround. Discover how you can skip the build and redeploy process by using JRebel by ZeroTurnaround.

One thing that puzzled me a little when I started out in Scala was the lack of interfaces and the choice of “traits” instead, which seemed to be a hybrid between interfaces and abstract classes from Java. How are you supposed to achieve clean polymorphism without interfaces I wondered?

Well, turns out what has a single solution in Java actually has a multitude of solutions in Scala, the obvious one is to use traits as straight interface replacements, and that certainly works.

However, there are two even more elegant solutions available in Scala that doesn’t force you to implement/extend a specific trait:

Function Passing
Given Scala’s functional aspects, one obvious alternative to traits is function passing. Say you want to do something with an InputStream, and you want to force the client of a function to have an “interface” that takes an InputStream as an argument and returns just about anything (or nothing). Well, that’s easy-peasy with Scala: 
  def getAbsoluteResource(path: String)(op: InputStream => Any) = {..}

def someInputStreamFunction(io: InputStream): Unit = {..}

// call the function:
In the actual call, we may replace the “someInputStreamFunction” with just about any other function, from any other object that conforms to the same contract. Why should we be forced extend specific traits and have specific names for our functions if that just works?

Also, this style of programming allows for some interesting things such as “around blocks”, which are in fact functions that take functions/function closures as an argument. This certainly makes lifecycle management a lot easier than the customary verbose Java-style of defining lifecycle methods on interfaces.
An example of this sort of “around” pattern with function passing is the below example of JPA transaction management with the recursivity-jpa library:
..your code within the transaction/persistence context goes here..
Structural Types/”Static Duck Typing”
How many times have you created interfaces like “Identifiable” with a “getId” method in Java merely to deal with entities that need persisting in a more generic way? I have, a lot. Well, Scala has a powerful little feature called “Structural Types” that can get rid of all of this - it is basically a means of enforcing a contract on a type without forcing it to extend anything else. You do this as follows:
def someFunction(identifiable: {def id: Long}){
..do stuff..
Here we have basically instructed the compiler to say that the function “someFunction” can take any argument that is of type “AnyRef”, but the AnyRef argument MUST have a function on it called “id” that returns a Long. Incidentally, for case classes, “def” will work fine with val’s and var’s defined in the case class constructor. Pretty neat, huh? Of course, you can further use structural types with casts in “asInstanceOf” or “isInstanceOf”, or combine it with Generics. In other words, you can enforce an old-school “Java interface” without having to explicitly implement an interface. The absolute prime example where this is useful is the case I already mentioned: in persistence code where entities need to be identifiable, but you don’t want to force a trait/interface down the throats of the entities.

So there you have it, a small primer of why Scala doesn’t need Java interfaces: Scala simply has more elegant ways of dealing with the same problem, without any of the weight that comes with Java interfaces.

This may be pretty basic stuff for the seasoned Scala developer, but I thought I’d put it down in writing so newbies have an easily accessible explanation for an issue that is quite a common question that I come across with people that are new to Scala.

The Java Zone is brought to you in partnership with ZeroTurnaround. Discover how you can skip the build and redeploy process by using JRebel by ZeroTurnaround.


Published at DZone with permission of Wille Faler , DZone MVB .

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}