The Artima Developer Community
Sponsored Link

Artima Developer Spotlight Forum
Traits in Scala

7 replies on 1 page. Most recent reply: May 2, 2008 12:18 PM by Bill Venners

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 7 replies on 1 page
Frank Sommers

Posts: 2642
Nickname: fsommers
Registered: Jan, 2002

Traits in Scala Posted: May 1, 2008 9:56 PM
Reply to this message Reply
Advertisement

Many developers coming to Scala after years of Java programming find that Scala aims to solve many of the pain points of Java programming. One such pain point is the way Java facilitates reuse of common behavior across classes. Java does not permit multiple inheritance, and its single-inheritance rule does not make it easy to share common base behavior in subclasses that would otherwise not share a common base class.

In his most recent IBM developerWorks article on Scala, Of traits and behaviors, Ted Neward explains the concept of traits, and how Scala helps developers define a clean object model:

Consider the fact that the Java language was created close to 20 years ago, in the heyday of "object-orientation." It was designed to mimic C++, the dominant language of the day, in a naked attempt to woo that language's developers over to the Java platform. Certain decisions were made that seemed obvious and necessary at the time, but in retrospect, we know that some of them are not as beneficial as the creators then believed. For instance, 20 years ago, it made sense to the creators of the Java language to reject both C++-style private inheritance and multiple inheritance. Since that time, many Java developers have had cause to regret their decision...

Tossing out private and multiple inheritance has cost us dearly in terms of code reuse. Java developers may rejoice in being free of virtual multiple inheritance, but the trade-off is often painstaking — and error-prone — work done by the programmer.

In the article, Neward walks through a typical JavaBean implementation, where property change listeners register and receive notifications of changes in the bean's state. Implementing common bean behavior in Java tends to be verbose, and Neward demonstrates how traits in Scala can reduce boilerplate code:

Scala enables you to define a new construct that lies halfway between an interface and a class, called a trait. Traits are unusual in that a class can incorporate as many of them as desired, like interfaces, but they can also contain behavior, like classes. Also, like both classes and interfaces, traits can introduce new methods. But unlike either, the definition of that behavior isn't checked until the trait is actually incorporated as part of a class. Or, put differently, you can define methods that aren't checked for correctness until they're incorporated into a trait-using class definition.

Traits offer a powerful mechanism for categorization and definition in Scala, both to define an interface for clients to use, a la traditional Java interfaces, and as a mechanism for behavioral inheritance based on other behaviors defined within the trait. Perhaps what we need is a new inheritance phrase, IN-TERMS-OF, to describe the relationship between a trait and an implementing class.

What do you think of Scala's traits?


Jose Cervera

Posts: 1
Nickname: jcervera
Registered: May, 2008

Re: Traits in Scala Posted: May 2, 2008 3:33 AM
Reply to this message Reply
The article was interesting, but I think it proved that the use of traits didn't simplify that much the addition of a property listener.

Wouldn't this have been 'easier' with the use of a AOP, defining a join point for the set* methods?

Alex Fabijanic

Posts: 71
Nickname: aleksf
Registered: Aug, 2006

Re: Traits in Scala Posted: May 2, 2008 4:34 AM
Reply to this message Reply
> The article was interesting, but I think it proved that
> the use of traits didn't simplify that much the addition
> of a property listener.

I agree - there is no simplification to speak of. The interesting portion are the chapter opening quotes. Indeed, conclusions are not always pleasant. Forgetful of the past are doomed to repeat it - I don't quite know what to make of "definition that is not checked until incorporated" presented as an improvement. In C++ world, it is believed to be a problem (addressed with upcoming concepts). Author begins the article saying that the issues addressed have already been solved long time ago, wrongfully abandoned and are now revisited. It ends with a "new phrase" introduction (IN-TERMS-OF) - an idiom known for decades. There may be more to Scala than shown in the article, but it did not make me want to download it.

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: Traits in Scala Posted: May 2, 2008 9:40 AM
Reply to this message Reply
> The article was interesting, but I think it proved that
> the use of traits didn't simplify that much the addition
> of a property listener.

I find it annoying that most people assume POJO -> Bean. Implementing a bean means a number of requirements must be met above and beyond what is required to implement an object in Java. How can a Bean be a plain old Java object? And if "POJO" just means "Bean" then why the hell did we need a new word for that?

I digress so the problem here is that the bean concept is one more suited for dynamic languages. The problem of adding listener support is easily solved once and for all with a proxy object in Python, for example. This makes it a very poor example for demonstrating the value of traits.

In static languages, I think it would make more sense to scrap beans and implement an abstraction for providing properties and information about them (basically a fancy map) then to force a new class to be created every time you need a new set of properties.

Bill Venners

Posts: 2284
Nickname: bv
Registered: Jan, 2002

Re: Traits in Scala Posted: May 2, 2008 9:49 AM
Reply to this message Reply
> The article was interesting, but I think it proved that
> the use of traits didn't simplify that much the addition
> of a property listener.
>
> Wouldn't this have been 'easier' with the use of a AOP,
> defining a join point for the set* methods?
>
That would help with defining the set methods, but wouldn't you still need to write the add/remove property change listener methods? I agree this may not be a very compelling example for traits, but what Ted is showing is that you can mix in the add/remove property change listener methods with the trait. The other design issue I'd raise with Ted's example, though, is that the firePropertyChange method is going to be public in the class that mixes in the BoundPropertyBean trait. It should not be.

The three main things to know about traits is that they are just like classes, except:

1. their constructor can't take parameters
2. although you can only extend one superclass, you can mix in multiple traits
3. the meaning super in a trait is not defined until you mix it into a class

What's delayed is the definition of super. That's how traits differ from traditional multiple inheritance, and that's how they avoid the diamond problem. This is the real difference between Scala's traits and C++'s multiple inheritance, and it makes traits much more useful in comparison.

The type of this is known when you write the trait. By default it is the trait type, but it can be defined to be a different type. If you do that, the trait can only be mixed into a class that when instantiated will be an instance of that named type. That's how you can state a dependency, a type that the trait needs, when you define the trait. So if you say your this is of type Elevator, then that trait can only be mixed into Elevator or one of Elevator's subclasses. I think this may be what Ted is referring to when he says that "you can define methods that aren't checked for correctness until they're incorporated into a trait-using class definition." But really everything is type checked at every compile. So I think "not checked for correctness" is a poor choice of words.

The other thing I'd point out is that Scala has a much more concise way to do accessor methods. Where you'd do this in Java:


//This is Java
public class Person
{
private String lastName;
private String firstName;
private int age;

public Person(String fn, String ln, int a)
{
lastName = ln; firstName = fn; age = a;
}

public String getFirstName() { return firstName; }
public void setFirstName(String v) { firstName = v; }
public String getLastName() { return lastName; }
public void setLastName(String v) { lastName = v; }
public int getAge() { return age; }
public void setAge(int v) { age = v; }
}


In Scala, you'd do this:

class Person(
var firstName: String,
var lastName: String,
var age: Int
)


That's it. That gives you a constructor that takes those three parameters, private fields to store them, and accessor methods. The accessor methods have names that allow you to use them this way:


val bob = new Person("Bob", "Jones", 29)
bob.age = 31 // Be honest, Bob
println(bob.age)


It looks like you're accessing a public field, but you're really going through accessor methods. So you could define them yourself if you wanted to add behavior, such as throwing an exception if someone tries to set a negative age or empty or null name. If you need JavaBeans style set and get methods, Scala has a standard annotation you can use to get them:


import scala.reflect.BeanProperty

class Person(
@BeanProperty var firstName: String,
@BeanProperty var lastName: String,
@BeanProperty var age: Int
)


You can't call the set and get methods from within Scala, but they are there on the class, so tools like Hibernate, etc., can call them. From Scala, you are forced to use the prettier syntax I showed above, which looks like field accesses.

In Ted's example, though, he wants to fire a property change event anytime the set method is called. So that's why he had to define the set methods explicitly in his example. The set method you get with BeanProperty just sets the field. It won't call firePropertyChange method.

Morgan Conrad

Posts: 307
Nickname: miata71
Registered: Mar, 2006

Re: Traits in Scala Posted: May 2, 2008 10:31 AM
Reply to this message Reply
Bill, in these languages that automatically give you accessors, how do you make them immutable / read-only? e.g. I want to allow


if (bill.age > 50)
startSendingAARPmaterials();


but not allow


bill.age = 21; // fake ID to allow Bill to buy beer

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: Traits in Scala Posted: May 2, 2008 10:39 AM
Reply to this message Reply
> Bill, in these languages that automatically give you
> accessors, how do you make them immutable / read-only?

IIRC in Scala you declare it as a 'val' instead of a 'var'.

Bill Venners

Posts: 2284
Nickname: bv
Registered: Jan, 2002

Re: Traits in Scala Posted: May 2, 2008 12:18 PM
Reply to this message Reply
> Bill, in these languages that automatically give you
> accessors, how do you make them immutable / read-only?
> e.g. I want to allow
>
>

> if (bill.age > 50)
> startSendingAARPmaterials();
>

>
> but not allow
>
>

> bill.age = 21; // fake ID to allow Bill to buy beer
>


As James pointed out, in Scala you just say val instead of var. val defines a variable that can be initialized, but not reassigned:

class Person(
val firstName: String,
val lastName: String,
val age: Int
)

If you need the JavaBeans get methods, you'd say:

import scala.reflect.BeanProperty

class Person(
@BeanProperty val firstName: String,
@BeanProperty val lastName: String,
@BeanProperty val age: Int
)

Flat View: This topic has 7 replies on 1 page
Topic: Traits in Scala Previous Topic   Next Topic Topic: Sun Releases NetBeans 6.1

Sponsored Links



Google
  Web Artima.com   

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