Thursday, February 13, 2014

Scala Traits Tutorial - Part 2 (Objects with Traits)

In my previous tutorial on Scala traits, I talked about the motivation behind traits and how they can be used to solve problems that crop-up in other languages, due to the lack of traits. It's obvious, from my previous tutorial, that traits can be used in the same way that interfaces are used in Java. But, traits can also contain default/concrete implementations, which gives us added benefit. In this tutorial, I'm going to give some examples of how you can instantiate classes and mix-in traits at the time the object is defined.

Using the same example as the first tutorial, let's assume we have a trait for a WorkVehicle, as follows.

trait WorkVehicle {
  def towWeight: Integer = {
    return 2500
  }
}

This trait has a default/concrete implementation for the towWeight method. Next, let's consider a class for a PersonalVehicle that extends a base abstract class called Vehicle. Note that the class itself does not mix-in the WorkVehicle trait.

abstract class Vehicle

class PersonalVehicle extends Vehicle

Rather than creating a new class that mixes-in the WorkVehicle trait, we can do this at the time the class is created, like such.

val myWorkVehicle = new PersonalVehicle with WorkVehicle

This is a powerful feature. It allows us to mix-in traits for individual objects, only when needed, rather than doing it at the time that the class is designed. Very cool!

Tuesday, February 11, 2014

Scala Traits Tutorial - Part 1

One thing I hear from people new to Scala is confusion around traits. How are they different than an abstract class, what are some real-world use cases for traits, and how do you know when to use a trait versus an abstract class, etc. These are all questions that come up quite a bit with new Scala developers. So, I thought it would be a good idea to write a series of articles around traits.

In this first article on traits, I'm going to discuss two topics regarding traits:

  • What is the motivation behind traits and why do we need them?
  • How can we use traits to accomplish what C++ gives us with multiple inheritance?

Let's start by talking about why traits are needed. Most of us Java programmers spent some time writing OOP code in C++. In C++, we had multiple inheritance. As powerful as it seems, multiple inheritance can lead to a ton of problems in the world of OOP. For example, what if we are designing an inventory system for an automotive dealership that specializes in selling both personal vehicles and work vehicles. We decide to create a class called "WorkVehicle" and "PersonalVehicle". Both classes inherit from a base class called "Vehicle". But along comes a new vehicle to the market that is both a personal vehicle and a work vehicle. So, we create a new class called "HybridVehicle" that extends both WorkVehicle and PersonalVehicle. The end-result is a messy class diagram that illustrates the dreaded diamond inheritance relationship. We now have to code around the merging of common fields.





Java decided that this is enough of a problem, that it's excluded from the language altogether. You're just now allowed to extend multiple classes. However, this scenario crops-up fairly often in software development, where we need to model entities that share characteristics with other entities in the system, but a parent-child relationship isn't the appropriate fit. Scala's answer to this problem is traits. A Scala trait can have a combination of abstract methods and methods with default implementation.

Let's look at a simple example of how the vehicle problem might be solved using a trait. In the code example below, we have an abstract class named Vehicle. We've extended Vehicle to create a PersonalVehicle class. We've realized that the thing that makes a WorkVehicle a "vehicle capable of doing work" is that it has a weight that it can safely tow/haul, so we've created a trait called WorkVehicle. This trait has a method with a default implementation, which can be overridden if you need. Notice the use of the with keyword when we mix-in a trait.


abstract class Vehicle

class PersonalVehicle extends Vehicle

trait WorkVehicle {
  def towWeight: Integer = {
    return 2500
  }
}

class HybridVehicle extends PersonalVehicle with WorkVehicle


This should illustrate how easy it is in Scala, to model various characteristics of objects using traits and mix-in these traits where we need. The result is a clean relationship that you don't get with multiple inheritance in C++, yet we still have the same power that we like out of multiple inheritance, which Java doesn't provide.