Sponsored Link •
|
Summary
There is a lot of interest currently in the ability to extend a class (or something close to class extension) without requiring recompilation or source changes, Traits offer a viable method of achieving this.
Advertisement
|
Traits are like interfaces, but can have a method body and a class that implements a Trait inherits the method body. In many ways Traits are similar to abstract classes, but they don't have constructors, don't have initializers, don't have fields, can be multiply inherited (like an interface), and super
does not refer to a method in an inherited trait, instead of super
you have to qualify the intended name [TraitName].[methodName]( ... )
.
By way of example consider current best practice: you write an interface, e.g. List
, write a useful abstract class to make writing lists easier, AbstractList
, and then implement some lists, e.g. ArrayList
. This is all well and good, but suppose you now want to add some extra methods to List
, e.g. sort
. You can't because every class that implements List
would need to add a sort
method and you don't have control over all the source that uses List
. So instead you use a helper class, Collections
, and add sort
as a static method. The user then calls sort( list )
(assuming a static import is used). A better technique is a Trait, with a trait you modify List
:
public interface List extends Collection { ... void sort() { ... } // same syntax as an interface but allows method bodies }
ArrayList
now automatically pick up sort
and the user does not need a special import, instead just like any other instance method the user writes list.sort()
.
With Traits, if there is a conflict due to multiple inheritance then you have to resolve this conflict (this is a key difference from Mixins - see below). E.G.:
interface X { int m() { return 1; } } interface Y { int m() { return 2; } } interface Z extends X { int m() { return 3; } } class XY implements X, Y { // conflict - 2 m's public int m() { return X.m(); } // resolve conflict } class XZ implements X, Z {} // no conflict - Z's m overrides X's
The difference between a Trait and a Mixin is that order is important. In the class XY
example given above, with a Trait you have to explicitly say which m
you want. With a Mixin the order in which the interfaces are mixed in determines what happens. class XY implements X, Y {}
is read as first mixing in X
then mixing in Y
; hence the m
from Y
overrides the m
from X
, since it is mixed in afterwards.
An alternative way of adding methods to a class is Extension Methods, these are proposed for Java 7, but have a number of problems.
To be able to add methods to an interface without recompiling, all clients of the interface, the class loader has to be extended to automatically add in the extra methods if they are not present and to flag an error if an unresolved conflict exists. Currently the class loader flags a missing method, the required extra action would be to see if the missing method is in an implemented interface and if it can be added without conflict.
Traits would be a viable alternative to abstract classes in many cases, for example the methods in AbstractCollection
could be moved to Collection
and no one would need to use AbstractCollection
in the future. But a Trait cannot have any fields, therefore some abstract classes, e.g. AbstractList
(it contains a field) would still be needed, although some methods may be moved to an interface.
I think Traits would be a useful addition to Java, what do others think?
Have an opinion? Readers have already posted 20 comments about this weblog entry. Why not add yours?
If you'd like to be notified whenever Howard Lovatt adds a new entry to his weblog, subscribe to his RSS feed.
Dr. Howard Lovatt is a senior scientist with CSIRO, an Australian government owned research organization, and is the creator of the Pattern Enforcing Compiler (PEC) for Java. PEC is an extended Java compiler that allows Software Design Patterns to be declared and hence checked by the compiler. PEC forms the basis of Howard's 2nd PhD, his first concerned the design of Switched Reluctance Motors. |
Sponsored Links
|