Skip to content
Print

Scala for Java Refugees Part 5: Traits and Types

4
Feb
2008

One of the mantras repeated throughout this series has been that Scala is Java, just better.  Thus it stands to reason that Scala would at a minimum support all of the features and power that Java offers.  So far you’ve seen things like object-oriented constructs, the power of methods and even dabbled a bit with pattern matching.  Through all this, I’ve deliberately avoided a particularly obvious Java construct: interfaces.

Interfaces (or are they?)

Scala doesn’t have any direct analogue to Java’s interfaces.  This answer may seem a bit surprising, given what I’ve been saying about similarity to Java.  The fact is that Java’s interfaces are really a very weak mechanism and a paltry imitation of their forebear: multiple inheritance.

Back in the days of C++, when the power of the dark side waxed full, object oriented languages commonly had support for inheriting from more than one superclass.  In C++, you could see this in examples like the following (shamelessly stolen from Wikipedia):

class Person {
public:
    virtual Schedule* get_schedule() const = 0;
};
 
class Student : public Person {
public:
    Student(School*);
 
    Schedule* get_schedule() const {
        return class_schedule;
    }
 
    void learn();
 
private:
    Schedule *class_schedule;
};
 
class Worker : public Person {
public:
    Worker(Company*);
 
    Schedule* get_schedule() const {
        return work_schedule;
    }
 
    void work();
 
private:
    Schedule *work_schedule;
};
 
class CollegeStudent : public Student, public Worker {
public:
    CollegeStudent(School *s, Company *c) : Student(s), Worker(c) {}
};

Looks fairly standard right?  The question comes when you call the get_schedule() function on an instance of CollegeStudent?  Think about it, what should happen?  Should you get a class schedule or a work schedule?

The answer is that nobody knows.  This is called the diamond problem and it’s something which annoyed computer scientists to no end in the early days of OOP.  Of course one solution to the problem is to just never use multiple inheritance.  Unfortunately, this becomes extremely restricting in certain situations which really call for the feature.

Java’s designers recognized the need for multiple typing (e.g. CollegeStudent is both a Student and a Worker), but they wanted to avoid the issues associated with inheriting conflicting method definitions along multiple paths.  Their solution was to design the interface mechanism, a feature which allows multiple typing without the complications of multiple inheritance.  So in Java you would represent the above sample like this:

public abstract class Person {
    public abstract Schedule getSchedule();
}
 
public interface IStudent {
    public void learn();
}
 
public interface IWorker {
    public void work();
}
 
public class Student extends Person implements IStudent {
    private Schedule classSchedule;
 
    public Student(School school) {...}
 
    public Schedule getSchedule() {
        return classSchedule;
    }
 
    public void learn() {...}
}
 
public class Worker extends Person implements IWorker {
    private Schedule workSchedule;
 
    public Worker(Company company) {...}
 
    public Schedule getSchedule() {
        return workSchedule;
    }
 
    public void work() {...}
}
 
public class CollegeStudent extends Person implements IStudent, IWorker {
    public CollegeStudent(School school, Company company) {...}
 
    public Schedule getSchedule() {...}
 
    public void learn() {...}
    public void work() {...}
}

Holy long examples, Batman!

If the sheer verbosity of the example wasn’t enough to convince you of its flaws, direct your attention to the CollegeStudent class.  We’ve achieved our primary goal here of creating a class which is both a Student and a Worker.  Unfortunately, we had to implement the learn() and work() methods multiple times.  Also, we complicated our hierarchy by a factor of two and introduced the much-despised IRobot convention.  Finally, our hierarchy is less constrained than the C++ version in that there’s nothing to prevent us from creating workers which are not people.  Logically this makes sense, but our specification says that all students and workers should be people, not insects or computers.  So we’ve lost flexibility, been shouldered with verbosity and introduced redundancy, all in the attempt to avoid a trivial logical disjunction.

Traits

Scala recognizes that interfaces have their issues.  So rather than blinding creating a reimplementation of the same problems found in either Java or C++, Scala takes a new approach.  Inspired by a combination of Java’s interfaces and Ruby’s mixins, the designers of Scala have created the trait construct.

trait Book {
  def title:String
  def title_=(n:String):Unit
 
  def computePrice = title.length * 10
}

Scala’s traits are quite nice in that they can not only define abstract members, but also full method definitions.  At the same time, they allow inheriting classes to inherit from more than one trait.  They pass on their type information and implementations to their children, as well as enforcing the abstract members.  At first glance, this seems like it would be just as bad as straight-up multiple inheritance, but it turns out the problems have been mitigated in some very clever ways.

To start with, there’s that ever-annoying override keyword.  I mentioned back in the article on basic OOP that any method which overrides a method in a superclass must be declared with the override modifier.  At the time, I likened it to the language mandating the use of the @Override annotation, with its primary purpose being to enforce the good practice.  The keyword however serves a far more important purpose, as we’ll see in a second.

The real key to the power of traits is the way in which the compiler treats them in an inheriting class.  Traits are actually mixins, not true parent classes.  Any non-abstract trait members are actually included in the inheriting class, as in physically part of the class.  Well, not physically, but you get the picture.  It’s as if the compiler performs a cut-and-paste with the non-abstract members and inserts them into the inheriting class.  This means that there’s no ambiguity in the inheritance path, meaning no diamond problem.  We can rewrite our CollegeStudent example in Scala without redundancy or fear of paradox:

abstract class Person {
  def schedule:Schedule
}
 
trait Student extends Person {
  private var classSchedule:Schedule = ...
 
  override def schedule = classSchedule
 
  def learn() = {...}
}
 
trait Worker extends Person {
  private var workSchedule:Schedule = ...
 
  override def schedule = workSchedule
 
  def work() = {...}
}
 
class CollegeStudent(school:School, company:Company) extends Student with Worker {
  // ...
}

Now if we make a call to the schedule method on an instance of CollegeStudent, the compiler knows that we’re referring to the implementation of schedule in the Worker trait.  This is because Worker was mixed in after the Student trait.  We could just as easily reverse the order and make the Student implementation the dominant one:

class CollegeStudent(school:School, company:Company) extends Worker with Student {
  // ...
}

Now Student#schedule is the dominant implementation while the implementation in Worker is overridden.  This is where the override keyword becomes extremely useful.  It’s sort-of the last stop fallback to ensure that no ambiguities sneak into the hierarchy without glaring compiler errors.

The absolutely most important thing to notice in the example, aside from the multiple-inheritance, is that CollegeStudent is actually a proper sub-type of Person, Student and Worker.  Thus you can operate on an instance of CollegeStudent polymorphically as an instance of one of these super-traits. In fact, other than the whole mixin thing, Scala traits are pretty much just like abstract classes.  They can declare abstract members, non-abstract members, variables, etc.  They can even extend other classes or traits!  The one catch is that Scala traits cannot accept parameters in their constructor.

This means that in one sense, the C++ version of our CollegeStudent snippet is more powerful than the Scala translation.  In Scala, the Student and Worker traits cannot have constructor parameters, so there’s no way to specify a School or Company as part of the inheritance.  If you ask me, it’s a small price to pay for all of this power.  And no matter which way you slice it, traits are still far more flexible than Java interfaces.

Type Parameters

You may not have realized this, but Scala is a statically typed, object-oriented language.  There are many such languages (C++, Java, etc), but they all have a common problem: accessing instances of a specific type from within a container written against a supertype.  An example serves better here than an explanation:

ArrayList list = new ArrayList();
list.add("Daniel");
list.add("Chris");
list.add("Joseph");
 
String str = (String) list.get(0);

The last line requires the cast because although we know that list only contains String(s), the compiler doesn’t know it.  As far as the compiler is concerned, it’s just a list of Object(s)From the beginning though, this has been a problem for Java.  It has lead to mountains of ugly code and nasty casts to try and trick some type-safety into generic contains.  Enter type parameters.

Java 5 saw the introduction of a feature called “generics”.  Just about every other language calls them “type parameters”, so I tend to use the terms interchangeably.  Java’s generics allow developers to specify that an instance of a generic type is specific not to the supertype but to a specific sub-type.  For example, the above example rewritten using generics:

ArrayList<String> list = new ArrayList<String>();
list.add("Daniel");
list.add("Chris");
list.add("Joseph");
 
String str = list.get(0);

Not only have we avoided the cast on the final line, but we have also added type-checking to all of the add() invocations.  This means that the compiler will only allow us to add String instances to the list.  This is quite nice of course, but it has its limitations.

Because Java 5 was striving to maintain backward compatibility with old code-bases, the generics implementation isn’t as flexible as it could be.  Most of this inflexibility stems from the decision to implement generics using type erasure, rather than reified types.  However, there are other issues which make working with Java generics weird, such as the incredibly cryptic and inconsistent syntax.  In short, Java generics are a language afterthought, whereas Scala type parameters were designed into the language from day one.

Scala type parameters have a lot of nice things going for them.  Perhaps number one on the list is a more consistent syntax.  Rather than a generics-specific wildcard character ( ? ) and an overloading of the extends keyword, Scala type constraints utilize operators and meta-characters which are consistent with the rest of the language.  But I’m getting ahead of myself…

This is how the list example might look translated into Scala:

val list = new ListBuffer[String]
list += "Daniel"
list += "Chris"
list += "Joseph"
 
val str = list(0)

Passing over the operator overloading ( += ), the important thing to notice is the syntax of the ListBuffer type parameter.  You’ll notice that Scala uses square brackets rather than greater-than/less-than symbols to denote type parameters.  This is a bit counter to the traditional syntax (handed down from C++), but it turns out to be quite clean and powerful.  Here’s a simple, parameterized class:

class MyContainer[T] {
  private var obj:T = null
 
  def value = obj
  def value_=(v:T) = obj = v
}
 
val cont = new MyContainer[String]
cont.value = "Daniel"
 
println(cont.value)

With the exception of the square brackets, the syntax is remarkably similar to Java’s.  Unlike C++, there’s no weird template typing; no mind-numbingly verbose method prefixing.  Just solid, clean code.

Now Java allows generics to implement type constraining, which forces the type parameter to satisfy certain conditions.  (extending a certain supertype is a common example)  This can be accomplished easily through Scala, and as I said before, without overloading a keyword:

import scala.collection.mutable.HashMap
 
import java.awt.Component
import javax.swing.JLabel
 
class MyMap[V<:Component] extends HashMap[String,V]
 
val map = new MyMap[JLabel]
map += "label1" -> new JLabel()
map += "label2" -> new JLabel()

In the class MyMap, the single type parameter must be a subtype of Component, otherwise the compiler will throw an error.  This of course is specified using the <: operator, rather than the extends keyword as it would be in Java.  This has two advantages.  1) it avoids overloading the definition of a basic keyword, and 2) it allows for lower type bounding without unintuitive constructs.

Lower type bounding is when the type parameter is constrained such that a certain type must inherit from the type parameter.  This is accomplishable in Java, but only by doing some extremely weird rearranging of the generic definition.  In Scala, it’s as simple as switching the direction of the type constraint operator:

class MyMap[V:>CollegeStudent] extends HashMap[String,V]

In this declaration, type parameter V can be any type which is extended by CollegeStudent (from our earlier example).  Thus the parameter could be Student, Worker or even Person.  Obviously, this is a lot less useful than specifying an upper type bound, but it still has applications, especially in some of the core Scala classes.

Just like Java, Scala allows type parameters on methods as well as classes:

def checkString[A](value:A):A = {
  value match {
    case x:String => println("Value is a String")
    case _ => println("Value is not a String")
  }
  value
}
 
val test1:String = checkString("Test Value")
val test2:Int = checkString(123)

As you can see, Scala extends its type inference mechanism to type parameters similar to how Java does.  I could just as easily have left the explicit type declarations off of the two values and Scala would have properly inferred the types from the return types of the corresponding checkString() invocations.  This is of course very similar to how Java allows method type parameter inference (see the Arrays#asList(T…) API).

Again much like Java, Scala allows explicit specification of method type parameters.  For example, this is the unsafe idiom to cast objects in Scala (the “sanctioned” syntax is to make use of pattern matching):

val obj:Object = "Test String"
val str:String = obj.asInstanceOf[String]

Here we are explicitly specifying String as a type parameter to the asInstanceOf method.  This method returns an instance of class String generated from the instance of class Object in the obj value.

In truth, we’ve barely scratched the surface of the capabilities of Scala’s type parameter mechanism.  If you’re looking for some brainf*ck of an evening, I suggest you read up on Scala type variances.  If there was any doubt that Scala is a more powerful language than Java, it will be quickly dispelled.  :-)

Oh, as a side note, Scala type parameters are currently (as of version 2.6.1) not quite compatible with Java generics.  While you can use parameterized Java classes, specifying the type parameters using the Scala syntax (e.g. new ArrayList[String]), you cannot actually declare parameterized Scala classes to be usable from within Java.  According to the mailing-lists however, the next release of Scala will indeed have full cross-compatibility between Scala and Java in the area of type parameterization.

Conclusion

The deeper we go in the Scala language, the more we realize the truly awesome power of its syntax.  What’s really amazing though, is that the designers were able to create a language with such flexible constructs without sacrificing the underlying clarity and consistency of the syntax.  At first blush, Scala continues to look a lot like Java and remains extremely readable to the average developer.  Somehow this clarity is retained without coming at the expense of capability.  Traits and Scala’s type parameters are just one more example of this fact.

Coming to you in the sixth and final installment: a few steps into the wonderful world of Scala-specific syntax.

Comments

  1. How is :> different to super? And Scala uses erasure just like Java.

    Asd Monday, February 4, 2008 at 3:13 am
  2. Sorry, but Scala hasn’t solved the multiple-inheritance problem any more than C++ has.

    The practical problem with multiple inheritance was always about correctly maintaining the internal state of super-classes when a single method is overridden by more than one super-class.

    For example, what if both Student and Worker modified some internal state when getSchedule() was called. Now, because one of those methods takes precedence, one of the super-traits is going to get out-of-sync.

    When your hierarchy gets several layers deep, these kinds of problems can become horribly difficult to debug.

    Noel Grandin Monday, February 4, 2008 at 6:52 am
  3. You skipped over an important issue in the multiple-inheritance example:

    How does a student (who has both a school schedule and a work schedule) expose his work schedule?
    – You might say that the student has access to the private vals workSchedule and schoolSchedule, but
    (a) those are private, not public, and
    (b) there’s a hard dependenciy between Student, and Worker, to maintain different names for their schedule attributes, so the problem isn’t solved at all!

    I would hope and guess that there would be (automatically-created) methods like
    CollegeStudent#Student#schedule and
    CollegeStudent#Worker#schedule

    (like Haskell’s ‘modules’, where ambiguous inheritance is resolved by requiring that each use be prefixed by a disambiguating module name)

    so that, like implicit defs, ambiguity can be resolved by calling an explicit lexical container.

    Otherwise, the multiple-inheritance isn’t solved at all, it just fails in a predictable way, the arbitrary choice based on order of traits on the class declaration line.

    There must be a better way!

    Mike Monday, February 4, 2008 at 9:18 am
  4. Apologies for my self-followup, but, would this work? Is it a good idea?

    collegeStudent = new CollegeStudent()
    classSchedule = collegeStudent.asInstanceOf[Student].schedule
    workSchedule = collegeStudent.asInstanceOf[Worker].schedule

    Seems it would work, but ‘asInstanceOf’ smells bad.

    How about downcasting?

    classSchedule = (collegeStudent: Student).schedule
    workSchedule = (collegeStudent: Worker).schedule

    ??

    Mike Monday, February 4, 2008 at 10:02 am
  5. Nice article! Appreciate the simple explanation and examples for traits and type constraining operators.

    Steve Yen Monday, February 4, 2008 at 10:27 am
  6. Nice and interesting article!

    I believe the Java multiple inheritance example has an error though. CollegeStudent doesn’t have an implementation of the abstract method getSchedule, and so the ambiguity still exists in that example. Did you mean for CollegeStudent to inherit from Student instead of Person?

    Hans-Eric Grönlund Monday, February 4, 2008 at 11:57 am
  7. Thanks for this explanation. I’ve just started to get into Scala and any good information is more than welcome.

    Markus Jais Monday, February 4, 2008 at 12:06 pm
  8. Minor follow-up: “…Passing over the operator overloading…”, is slightly incorrect as they are not really operators, they’re just method names (that look like operator in other languages).

    M. Ibrahim Monday, February 4, 2008 at 12:25 pm
  9. @M. Ibrahim
    Very true that Scala operators are in fact methods. However, any language which supports operator overloading will satisfy this property, so I didn’t consider it worth mentioning. It is true though that Scala takes the concept much further than languages like C++ or even Ruby.

    @Hans
    Nice catch! I’ve updated the article. I could have inherited from Student, but I wanted to accentuate that CollegeStudent is a hierarchical peer of Student and Worker, rather than a subtype of both.

    @Mike
    I haven’t actually tried it, but I would assume that downcasting wouldn’t be helpful with traits because it is in fact a mixin, not an inheritance. Casting to a super-trait and calling a conflicting method would just call the implementation as chosen by the mixin conflict in the sub-class.

    As a side note, asInstanceOf really is a bad idea, though it’s not the worst thing in the world. :-) It’s just syntactic sugar around a match statement, so not too horrible. As I mentioned above though, I don’t think it would help with the mixin conflict issue.

    @Noel
    Darn, you caught me! :-) Yes I did skip a rather significant issue with multiple inheritance, that of side-effects. You are quite correct that this can be a confusing issue when debugging a large hierarchy. It is avert however by two things:

    1) Clean, functional-style programming: You don’t have to write everything as a recursive function, but taking care to avoid unnecessary side effects where possible can really clean up your hierarchy
    2) Developer common-sense: Any “feature” in a language is really just a bug that’s going to fail predictably. Programming can be thought of as a set of techniques which cause the computer to crash predictably, producing a desired side-effect. Ambiguity kills in situations like this, which is primarily why C++’s multiple inheritance is so horrible. Scala doesn’t solve all of the problems with multiple inheritance, just the really killer ones.

    @Asd
    In Java:

    public void operate(T value) {…}

    In Scala:

    def operate[T:>String](value:T) = {…}

    In both cases, T has a lower type bound of String, which means it could represent an instance of CharSequence, Object, etc. The two syntaxes accomplish roughly the same thing, but I prefer the Scala form simply because it looks clearer to me. The Java syntax makes you stop for a second and ponder the logical ins and outs before you can decipher its meaning, whereas the Scala :> operator is fairly intuitively obvious (I think).

    I didn’t really show the areas where Scala’s generics seriously outshine Java’s (such as type variances). As you said, Scala’s generics are also implemented using type erasure (I didn’t really make that clear in the article). However, the way in which this erasure is implemented avoids a lot of the weird errors and unintuitive type checking caused by Java’s implementation.

    Daniel Spiewak Monday, February 4, 2008 at 12:58 pm
  10. @Daniel: You said “If Ruby were statically typed, a method taking a parameter of type Singleton would not be able to accept an instance of TypeManager. Actually, you wouldn’t be able to define a method as taking an instance of Singleton since Singleton is actually a module, not a class.”

    Actually, kind_of? in Ruby also checks if a module is included, propagating the type of the module into the class of the including class.

    [].kind_of? Enumerable gives true. 1.kind_of? Enumerable gives false. (=== does it the opposite way – Enumerable === [], !(Enumerable === 1))

    This also means you can use Enumerable as a type in types.rb

    Eivind Eklund Tuesday, February 5, 2008 at 5:49 am
  11. Ah, I didn’t know that! That’s quite interesting. I wonder if that has implications on how the include statement works in other situations.

    Daniel Spiewak Tuesday, February 5, 2008 at 8:34 am
  12. Hi Daniel,

    A few reactions to this interesting post.

    * If I understood correctly, Scala traits don’t solve the Diamond problem: they just give you a way to prioritize which path of the diamond should dominate the other (this is already possible in C++ by prefixing the method you want to call with Class::, by the way), so I’m not sure that introducing them as solving the Diamond problem is the right angle.

    To me, traits and mixins enable reuse at a smaller scale than classes, and while I would like to see a similar feature in Java, I think C++ (despite its many flaws) can emulate them reasonably well with its multiple inheritance mechanism.

    * The fact that Scala traits can’t accept parameters in their constructor strikes me as an odd restriction. Of course, you can work around this by passing these parameters to the methods that use them, but this will probably cause redundancy and I can’t really come up with a good reason (philosophical or technical) to explain this restriction.

    * I am a bit skeptical about your claim “no matter which way you slice it, traits are still far more flexible than Java interfaces”. While technically correct (traits can be both an interface and an implementation while interfaces can only be… well, interfaces), I see the restriction that interfaces can’t contain an implementation as a good thing for reusability (and for other nice properties, such as testability, evolution, etc…).

    * I’m not sure I agree that using cryptic characters (:) is cute, but if you take a look at Perl, you will see how detrimental cuteness can be to languages that try to be too clever with their syntax.

    * Also, I think you are being a bit harsh on Java interfaces by emphasizing a flaw that rarely occurs in practice while ignoring all the good properties that they bring to the table.

    Good article overall, thanks!


    Cedric

    Cedric Tuesday, February 5, 2008 at 10:15 am
  13. Ok, my greater/less than signs were eaten, here it is again, properly escaped (I hope, would be nice to have a preview or to be able to edit a comment…).

    Hi Daniel,

    A few reactions to this interesting post.

    * If I understood correctly, Scala traits don’t solve the Diamond problem: they just give you a way to prioritize which path of the diamond should dominate the other (this is already possible in C++ by prefixing the method you want to call with Class::, by the way), so I’m not sure that introducing them as solving the Diamond problem is the right angle.

    To me, traits and mixins enable reuse at a smaller scale than classes, and while I would like to see a similar feature in Java, I think C++ (despite its many flaws) can emulate them reasonably well with its multiple inheritance mechanism.

    * The fact that Scala traits can’t accept parameters in their constructor strikes me as an odd restriction. Of course, you can work around this by passing these parameters to the methods that use them, but this will probably cause redundancy and I can’t really come up with a good reason (philosophical or technical) to explain this restriction.

    * I am a bit skeptical about your claim “no matter which way you slice it, traits are still far more flexible than Java interfaces”. While technically correct (traits can be both an interface and an implementation while interfaces can only be… well, interfaces), I see the restriction that interfaces can’t contain an implementation as a good thing for reusability (and for other nice properties, such as testability, evolution, etc…).

    * I’m not sure I agree that using cryptic characters (:<) is better than a full word (extends), even it means overloading it. The direction switching (:< and :>) is cute, but if you take a look at Perl, you will see how detrimental cuteness can be to languages that try to be too clever with their syntax.

    * Also, I think you are being a bit harsh on Java interfaces by emphasizing a flaw that rarely occurs in practice while ignoring all the good properties that they bring to the table.

    Good article overall, thanks!

    Cedric Tuesday, February 5, 2008 at 10:50 am
  14. Yeah, the next item on my TODO list is to fix up the comment engine a little bit. Agreed that the current version is lousy. :-S

    Perhaps I am being a bit too hard on interfaces. In truth, I adore the little buggers. They provide a lot of flexibility, both in allowing multiple super-types, but they can also be construed as a form of statically checked duck typing (program to the interface rather than the implementation). They aren’t *really* duck typing since you can’t just specify some arbitrary interface and accept all types which implement the relevant methods (since the type is actually part of the interface contract), but they are the closest thing Java has. I agree that I often find the “definition only” restriction to be an enabler of good design more than I find it to be restrictive of reuse.

    To clarify, I’m not saying that traits are always *better* than Java interfaces, just more capable. You can do a lot more with traits than you can with interfaces (as you pointed out).

    It is a fine line to walk between overly cryptic and overly verbose. Perl went too far to the cryptic side of life and now pays the price in the form of endless jokes and bad puns. I think in places, even Scala’s syntax crosses this line and allows, even encourages constructs which are extremely cryptic. (but concise!) I suppose it’s a matter of opinion about whether or not type constraints cross this line. Personally, I find the <: / :> syntax to be reminiscent of some of the symbols used in type theory, which is consistent with Scala’s academically algebraic roots. So is the syntax cryptic? Definitely. Is it *too* cryptic? Eh, draw your own conclusions. :-)

    I would define the “Diamond Problem” as referring to the paradox created by language ambiguity. Scala traits turn the diamond problem into a matter of bad design. So it’s still a “problem”, but it’s a problem which has a deterministic evaluation. I would certainly consider that to be an improvement.

    Daniel Spiewak Tuesday, February 5, 2008 at 11:21 am
  15. Would be nice if there were a way to get rid of the trait keyword. A trait would be declared as a class as any other class. “A designer knows he has achieved perfection not when there is nothing left to add, but when there is nothing left to take away”. Antoine de Saint-Exupery

    Oliver Plohmann Wednesday, February 6, 2008 at 4:11 am
  16. It should be mentioned that Scala traits are an “evolution” of the original concept of traits : traits in Scala are parameterless abstract classes. So that when you read about Squeak traits and then you are confronted with Scala traits your mind does not explode …
    See http://www.nabble.com/-scala–Traits-in-Scala-tt10784567.html#a10784567
    Not that I do not like the way Scala has implemented traits, but I find it annoying that one term ends up having so many definitions (closure …).

    javier Thursday, February 21, 2008 at 2:24 pm
  17. Hi Daniel,

    I’m loving your series of articles thus far. This is the first one I’ve commented on. I wanted to point out that overloading “extends” (in my humble opinion, of course) is no worse than overloading “&lt”. In fact, I’d argue that Scala heavily overloads parens, angle brackets, and many others, much more so than Java does. Flexible? Yes, definitely — but I wouldn’t say that somehow overloading “extends” (which starts with far fewer meanings than “&lt” and “&gt” do) doesn’t seem *that* bad. I think I’d prefer something else to signify structural type restrictions of a generic type.

    Martin Thursday, March 27, 2008 at 9:08 pm
  18. It’s surprising to see a language which obviously makes it possible to write some very clean looking code and even create DSL’s that look like written english, to use such an ugly operator as :>. That’s definately too perlish for my taste :)

    Anyways, great article series. Really got me started on learning Scala.

    Jaakko Thursday, April 16, 2009 at 2:26 pm
  19. “Inspired by a combination of Java’s interfaces and Ruby’s mixins, the designers of Scala have created the trait construct.”

    Traits were introduced by Prof.Ducasse at the University of Berne: http://citeseer.ist.psu.edu/566972.html and first implemented in Squeak Smalltalk. SInce Lausanne is not that far away from Lausanne, where the Scala resides, these people might have exchanged ideas …

    Klaus Loa Wednesday, August 26, 2009 at 6:19 am
  20. I know that the article is long gone, but:

    I think that traits are much better than interfaces. Why? Because you don’t have to use what they provide, but they give you some useful things. For example, the Monad trait, provided you implement flatMap[B](fn : A => M[B]) : M[B], defines the following for you:

    def flatMap[B, That](fn : A => M[B])(implicit bf : CanBuildFrom[M, B, That]) : That
    // flatMaps, then converts to type That, eg, from Array[T] to List[T], or String, Int…provided you can tell it how to do so with a CanBuildFrom subclass.
    def map[B](fn : A => B) : M[B]
    def map[B, That](fn : A => B)(implicit bf : CanBuildFrom[M, B, That]) : That
    // maps, then builds into type That.
    def foreach(fn : A => Unit) : Unit

    Don’t understand any of that? Good. You don’t have to, thanks to traits.

    anonymous Friday, October 29, 2010 at 1:53 pm
  21. @Cedric

    You missed the point of mixins. They completely solve the diamond problem because only duplicate methods which are from the EXACT SAME trait are resolved automatically. Any duplicates from different traits have to be resolved by the superclass in the single-inheritance chain (i.e. analogous to “Class::” in C++).

    You can’t do “Class::” specific method call from a trait (you must use the less specific “super.” instead), this because mixin order can insert an mixin in middle of the inheritance hierarchy of another mixin. For example, given mixin A (B) and mixin C (B), then mixin D (C,A) would effectively cause mixin C (A,B), because the B in mixin C (B) is already in the inheritance tree of mixin A (B), and thus not repeated. A more detailed explanation can be found at top, left of page 7 in the Super subsection of the 2.2 Modular Mixin Composition section of Scalable Component Abstractions, Odersky & Zenger, Proceedings of OOPSLA 2005, San Diego, October 2005.

    http://www.scala-lang.org/sites/default/files/odersky/ScalableComponent.pdf

    So I want you to realized that “Class::” specific method invocation can never be as flexible as mixins.

    I studied this deeply for the design of my Copute language.

    Shelby Moore III Sunday, February 13, 2011 at 2:12 am
  22. typo: I meant “…have to resolved by the subclass…”

    Shelby Moore III Sunday, February 13, 2011 at 2:14 am
  23. @Cedric

    Don’t conflate some programmer’s insufficient separation-of-concerns in the design of a trait with the Diamond Problem.The Diamond Problem is a specific problem of how to resolve multiple inheritance name spaces (scope).

    Also please realize that Scala is a single-inheritance language, with the apparency of multiple inheritance of traits. In reality, traits get folded into that single-inheritance chain in a specific order and are NOT multiply inherited.

    Shelby Moore III Sunday, February 13, 2011 at 2:24 am
  24. @shelby:

    Err…what?

    Yes, the compiler *does* do some clever tricks to fold MI into the inheritance chain. So?

    If you really wanted to, you could do the same thing for a language with ”no” proper implementation inheritance.

    interface Foo {
    Foo clone();
    Foo next();
    Foo plusBy(int n);
    }
    class Foo$class {
    static Foo plusBy(Foo this_t, int n) {
    Foo res = null;
    for (i = 0; i < n; i++) res = res.next();
    return res
    }
    }
    class Bar implements Foo {
    private int i;
    Bar(int i) {this.i = i}
    Foo clone() { return this; }
    Foo next() {return new Bar(i+1) }
    Foo plusBy(int n) {return Foo$class.plusBy(this, n)}
    }

    However, that’s really not the point. If there was a compiler that turned Scala into C++, then traits could become Multiple Inheritance proper. Yes, Scala doesn’t have full MI, but it does have some. Heck, even Java has some, with multiple interface inheritance.

    Actually, come to think of it, what you said isn’t strictly true. The implementation inheritance is folded away into the single-inheritance chain–well, actually, it’s usually folded into the class itself, but that’s not the point–but the interface of the trait is inherited as normal, and more than one interface may be inherited. Scala isn’t a strictly MI language, but don’t call it a Single-Inheritance one.

    anonymous Sunday, February 27, 2011 at 4:57 pm
  25. @anonymous
    I suggest re-read my prior comments more carefully, and study how Scala’s mixins really work and what they really do:

    http://copute.com/dev/docs/Copute/ref/class.html#Inheritance (review the references cited there for Scala too)

    There is no multiple inheritance. All implementation in traits are folded into the single-inheritance on per member basis and it is called “linearization”. And any duplicate members MUST be resolved by the subclass.

    Shelby Moore III Sunday, February 27, 2011 at 5:48 pm
  26. I think we may have different definitions of “multiple inheritance.” I think that Scala has limited multiple inheritance, although it is not full MI, via traits, because it can inherit method implementation from multiple sources (traits).

    anonymous Saturday, March 19, 2011 at 5:40 pm

Post a Comment

Comments are automatically formatted. Markup are either stripped or will cause large blocks of text to be eaten, depending on the phase of the moon. Code snippets should be wrapped in <pre>...</pre> tags. Indentation within pre tags will be preserved, and most instances of "<" and ">" will work without a problem.

Please note that first-time commenters are moderated, so don't panic if your comment doesn't appear immediately.

*
*