How to use Groovy Traits
Posted By : Rohan Jain | 18-Nov-2014
In this blog i'll discuss about one of the newer features of groovy, introduced with Groovy 2.3 release.
So What are Traits ?
Traits are reusable components basically set of methods or fields that you can make your class implement.
Why you should use them ?
You must have heard of problems of multiple inheritence when working with java and also familiar with the well known situation of what is know as 'Diamond problem'.It says that if you have two classes B and C inherit from A, and class D inherits from both B and C. If there is a method in A that B and/or C has overridden, and D does not override it, then which version of the method does D inherit: that of B, or that of C ??
e.g. source (http://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem )
Consider a scenerio of where we are developing a gui software and we create a class Button. Now according to appearance it can inherit from Rectangle Class and also inherit from Clickable due to the functionality i.e. handling input clicks. And the classes Rectangle and Clickable both inherit from the Object class. Now if we create a button object and calls the equals method for it and there is no such method in the Button class and we have an overridden method equals in our Rectangle or Clickable (or both) classes, so how do our button object decide to which method does it calls from its two parent classes (having method of same names)?
The situation is like we dont know from which parent class a particular feature is inherited from if more than one parent class implements the feature.
So traits allows the composition of behavior without going into the “diamond inheritance” problem allowing you to decide which behavior prevails upon conflict.
At first we'll see,
How to use them
Traits can be seen as interfaces carrying both default implementations and state.
A trait is defined using the trait keyword
trait HelloWorld { String helloworld() { "HelloWorld!" } }
Then we can use it like a normal interface using the implements keyword
class A implements HelloWorld {} def a = new A() assert a.helloworld() == "HelloWorld!"
How does it solve Multiple inheritance conflicts
trait A { String someMethod() { 'Do This' } } trait B { String someMethod() { 'Do That' } } class C {}
class C implements A,B {}
Default behaviour
when we call c.someMethod(), he default behavior is that methods from the last declared trait wins. Here, B is declared after A so the method from B will be picked up
assert c.someMethod() == 'Do That'
Desired behaviour
In case this behavior is not the one we want, we can explicitly choose which method to call using the Trait.super.foo syntax. In the example above, we can force to choose the method from trait A, by using this:
class C implements A,B { String someMethod() { A.super.someMethod() } } def c = new C() assert c.someMethod() == 'Do This'
You can also implement a Trait at Runtime as
trait Runtime { String runTimeMethod() { "I'm a run time method" } } class A { String someMethod() { 'Do This' } } def s = new A() as Runtime s.runTimeMethod() s.someMethod()
Implementing multiple traits at once
trait A { void methodFromA() {} } trait B { void methodFromB() {} } class C {} def c = new C() def d = c.withTraits A, B d.methodFromA() d.methodFromB()
Since Java 8 introduces default methods on interfaces Prior to Java 8, Java was not subject to the Diamond problem risk, as Java does not support multiple inheritance. The default interface method capability added with Java 8 introduced a type of multiple inheritance since classes can implement more than one interface, which can contain default methods that have the same name.
So how traits are differnet from Java 8 default methods
Traits behave the same but with a major difference: the implementation from the trait is always used if the class declares the trait in its interface list and that it doesn’t provide an implementation. Consider we have a class and a trait
Class A { void someMethod() { // Some implementation in super class for this method } } trait T { void someMethod() { // some different implementation in trait for the same method } }
Consider two classes that extends class A and implements trait T
class B extends A implements T {} class C extends A implements T {}
So even if we have someMethod() already implemented in the super class, but the classes B and C declares the trait in its interface list, the behavior will be borrowed from the trait implementation!
Cookies are important to the proper functioning of a site. To improve your experience, we use cookies to remember log-in details and provide secure log-in, collect statistics to optimize site functionality, and deliver content tailored to your interests. Click Agree and Proceed to accept cookies and go directly to the site or click on View Cookie Settings to see detailed descriptions of the types of cookies and choose whether to accept certain cookies while on the site.
About Author
Rohan Jain
Rohan is a bright and experienced web app developer with expertise in Groovy and Grails development.