Overriding traits in Scala

Under the very useful category, I find Scala’s functionality around traits to be extremely helpful. There are several related, more advanced topics to what I am about to demonstrate here (rich traits, structural types) but I wanted to step back a second to something very basic, since I have never addressed this here.

Let’s say you have an example where you have a user’s membership defined by an abstract class, and you have a basic member which implements it. This might be the REPL output.

scala> abstract class Member {
     | def memberId: Int
     | def firstName: String
     | def lastName: String
     | }
defined class Member

scala> class BasicMember(val memberId: Int, val firstName: String, val lastName: String) extends Member
defined class BasicMember

Next you want to create an upgraded membership. These members don’t just have a member id, name, and security role. They also begin accruing some kind of bonus points which they can redeem for products. For fun, we’ll call the bonus points “Buckoo Bucks.”

scala> trait BuckooBucks {
     | var buckooBalance: Int = 1000
     | def addBucks(amt: Int) = {
     | buckooBalance += amt
     | }
     | }
defined trait BuckooBucks

With this trait in place we can start creating members who use it:

scala> class BuckooMember(memberId: Int, firstName: String, lastName: String) extends BasicMember(memberId: Int, firstName: String, lastName: String) with BuckooBucks
defined class BuckooMember

The beauty is it really is as simple as that one line.

Now imagine you want to give basic members an incentive to sign up to start earning Buckoo Bucks. Let’s say that for a time you are going to double their points earnings.

This is as simple as defining a child trait to BuckooBucks with an abstract override of the addBucks method.

scala> trait DoubleBuckooBucks extends BuckooBucks {
     | abstract override def addBucks(amt: Int) = {
     | val doubledAmount = amt * 2
     | super.addBucks(doubledAmount)
     | }
     | }
defined trait DoubleBuckooBucks

Now you can add DoubleBuckooBucks to any member:

scala> val john = new BuckooMember(1, "John", "Public")

scala> val doublePointsJohn = new BuckooMember(1, "John", "Publi") with DoubleBuckooBucks
doublePointsJohn: BuckooMember with DoubleBuckooBucks = $anon$1@ac9e715

scala> john.addBucks(500)

scala> doublePointsJohn.addBucks(500)

scala> john.buckooBalance
res2: Int = 1500

scala> doublePointsJohn.buckooBalance
res3: Int = 2000

Pretty cool, eh?

Leave a Reply

Your email address will not be published. Required fields are marked *