The Artima Developer Community
Sponsored Link

Java Buzz Forum
Playing with Traits in Scala

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Lalit Pant

Posts: 51
Nickname: litan
Registered: Jun, 2007

Lalit Pant is a freelance programmer based out of Dallas, Texas
Playing with Traits in Scala Posted: Jun 22, 2007 9:50 PM
Reply to this message Reply

This post originated from an RSS feed registered with Java Buzz by Lalit Pant.
Original Post: Playing with Traits in Scala
Feed Title: All Things Runnable / Java
Feed URL: http://feeds.feedburner.com/lalitpant/java
Feed Description: Java related posts on Lalit Pant's Blog
Latest Java Buzz Posts
Latest Java Buzz Posts by Lalit Pant
Latest Posts From All Things Runnable / Java

Advertisement
Traits look like an interesting concept in Scala. Traits allow you to:
  • Define a type by specifying the signature of supported methods. This is similar to how interfaces work in Java.
  • Provide partial/full implementations that can be mixed-in to classes that use the trait. Why is this different from what abstract classes give you? The big difference is that abstract classes cannot be multiply extended from, while traits can.
This post starts to dig into how Scala traits work. I have used the following version of the Scala compiler for experimentation:
Scala compiler version 2.5.1-final -- (c) 2002-2007 LAMP/EPFL

Traits with only abstract methods get mapped to plain old interfaces by the Scala compiler. But when they contain implementations within non-abstract methods, traits start getting interesting. For such a trait (named, let us say - X), Scala generates two entities:
  • An interface called X with all the methods in the trait.
  • A class called X$class with static versions of all the non-abstract methods in the trait. These methods take one additional parameter (relative to the methods in the trait) of type X . Any code within a non-abstract method in the trait goes into the corresponding static method in X$class. Any calls to other trait methods from within this code get translated to calls on the extra parameter of type X.
A class that mixes-in X ends up:
  • Implementing the interface X.
  • Delegating all the non-abstract methods of X to the static methods of X$class, passing itself (this) as a parameter.
So, mixing-in a trait provides (in Java terminology) a concise and powerful way to implement an interface and delegate its implementation to another class.

Let us see some of this in action. But first a detour through Java-land to look at a problem that traits try to solve:

Let's say I have the following domain classes in a Java based system:
class Employee {
// etc
}

class Manager extends Employee {
List<Employee> directReports = new ArrayList<Employee>();

// etc
}
Now - let's say that I am given a new business requirement to implement:
Whenever a new Employee starts reporting to a Manager, a specified list of departments need to be notified of this change.

Let's also say that I have these infrastructure classes available to me:
interface Observer<T> {
void onChange(Observable<T> source, T notificationData);
}

interface Observable<T> {
void addObserver(Observer<T> observer);
void removeObserver(Observer<T> observer);
void notifyObservers(T notificationData);
}

class ObservableImpl<T> implements Observable<T> {
// manages sequence of observers and notifications to these observers
}
What I really want to do at this point is to make the Manager class Observable. I can then fire a notification to an Observer whenever a direct report is added to the Manager; this Observer can notify the appropriate departments about the change.

Wouldn't it have been great if I could do this:
class Manager extends Employee, ObservableImpl<Employee> {

List<Employee> directReports = new ArrayList<Employee>();

public void addReport(Employee e) {
directReports.add(e);
notifyObservers(e);
}

// etc
}
Alas, we don't have multiple inheritence in Java. So I have to go ahead and implement the Observable interface within the Manager class - and delegate to an ObservableImpl:
class Manager extends Employee implements Observable<Employee> {

List<Employee> directReports = new ArrayList<Employee>();

Observable<Employee> observable = new ObservableImpl<Employee>();

public void addReport(Employee e) {
directReports.add(e);
notifyObservers(e);
}

// etc

// implement Observable methods by delegating to observable

public void notifyObservers(Employee notificationData) {
observable.notifyObservers(notificationData);
}

public void addObserver(Observer<Employee> observer) {
observable.addObserver(observer);
}

public void removeObserver(Observer<Employee> observer) {
observable.removeObserver(observer);
}
}
Traits in Scala give me a short-cut way of doing this. Here's the same functionality implemented in Scala:
trait Observer[T] {
def onChange(source: Observable[T], notificationData: T) : Unit
}

trait Observable[T] {
def addObserver(observer: Observer[T]) = {/*do the right thing*/}
def removeObserver(observer: Observer[T]) = {/*do the right thing*/}
def notifyObservers(notificationData: T) = {/*do the right thing*/}
}

class Employee {}

class Manager extends Employee with Observable[Employee] {

var directReports : List[Employee] = Nil

def addEmployee(employee: Employee) = {
directReports = employee :: directReports
notifyObservers(employee)
}
}
Notice how much more concise the Scala version is. All you need to do is to declare Manager as:
class Manager extends Employee with Observable[Employee]
and this mixes-in the functionality of the Observable trait.

Neat, huh?

I haven't yet talked about a very useful trait pattern - in which a trait defines an abstract method (which needs to be implemented by classes that mix in the trait), and then uses this method to provide higher level value-added methods. A future post will dig into this...

Read: Playing with Traits in Scala

Topic: kelly12v24stor, by hufflepuffs from tumblr Previous Topic   Next Topic Topic: The Legion of the Bouncy Castle has released version 1.37 of the Bouncy Castle Java Cryptography...

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use