Designing with Groovy Traits - Gr8Conf India
-
Upload
naresha-k -
Category
Technology
-
view
933 -
download
3
Transcript of Designing with Groovy Traits - Gr8Conf India
Designing withGroovy Traits
Naresha K Chief Technologist
Channel Bridge Software Labs [email protected]
@naresha_k
The Problem
Bird charlie = new Bird()charlie.fly()
Butterfly aButterFly = new Butterfly()aButterFly.fly()
class Bird implements Flyable {def fly() {println "Flying..."
}}
class Butterfly implements Flyable {def fly() {println "Flying..."
}}
The Smell
class Bird implements Flyable {def fly() {
println "Flying..."}
}
class Butterfly implements Flyable {def fly() {
println "Flying..."}
}
DRYclass FlyableImpl implements Flyable {def fly() {println 'Flying...'
}}
class Bird implements Flyable {def fly() {new FlyableImpl().fly()
}}
Making it Groovierclass DefaultFlyable implements Flyable {def fly() {println 'Flying...'
}}
class Bird {@DelegateFlyable flyable = new DefaultFlyable()
}
Summarizinginterface Flyable {def fly()
}
class DefaultFlyable implements Flyable {def fly() {println 'Flying...'
}}
class Bird {@DelegateFlyable flyable = new DefaultFlyable()
}
Multiple Capabilities
trait CanSing {def sing() {println "Singing"
}}
trait CanDance {def dance() {println "Dancing"
}}
class Person implements CanSing, CanDance {}
Person reema = new Person()reema.sing()reema.dance()
Overriding Methods from a Trait
trait Speaker {def speak() {println "speaking"
}}
class Gr8ConfSpeaker implements Speaker {def speak() {println "Groovy is Groovy!"
}}
new Gr8ConfSpeaker().speak()
Traits can implement interfacesinterface Programmer {def code()
}
trait GroovyProgrammer implements Programmer {def code() {println 'coding Groovy'
}}
class Engineer implements GroovyProgrammer {}
new Engineer().code()
Traits can declare abstract methods
trait Programmer {abstract String getLanguage()def code() {println "Coding ${getLanguage()}"
}}
class GroovyProgrammer implements Programmer {String getLanguage() { "Groovy"}
}
new GroovyProgrammer().code()
Traits can have a state
trait Programmer {String languagedef code() {println "Coding ${language}"
}}
class GroovyProgrammer implements Programmer {}
new GroovyProgrammer(language: 'Groovy').code()
A trait can extend another traittrait JavaProgrammer {def codeObjectOriented() {println 'Coding OOP'
}}trait GroovyProgrammer extends JavaProgrammer {def codeFunctional() {println 'Coding FP'
}}class Engineer implements GroovyProgrammer {}Engineer raj = new Engineer()raj.codeFunctional()raj.codeObjectOriented()
A trait can extend from multiple traits
trait Reader {def read() { println 'Reading'}
}trait Evaluator {def eval() { println 'Evaluating'}
}trait Printer {def printer() { println 'Printing'}
}trait Repl implements Reader, Evaluator, Printer {}
The diamond problemtrait GroovyProgrammer {def learn() { println 'Learning Traits'}
}
trait JavaProgrammer {def learn() { println 'Busy coding'}
}
class Dev implements JavaProgrammer, GroovyProgrammer {}
new Dev().learn()
Finer control on the diamond problem
class Dev implements JavaProgrammer, GroovyProgrammer {
def learn() {JavaProgrammer.super.learn()
}
}
Applying traits at run time
trait Flyable{def fly(){println "Flying.."
}}
class Person {}new Person().fly()
Applying traits at run time
def boardAPlane(Person person) {person.withTraits Flyable
}
def passenger = boardAPlane(new Person())passenger.fly()
Composing Behaviours
trait UserContextAware {UserContext getUserContext(){// implementation
}}
class ProductApi implements UserContextAware {}
class PriceApi implements UserContextAware {}
common fieldstrait Auditable {String createdByString modifiedByDate dateCreatedDate lastUpdated
}
class Price implements Auditable {String productCodeBigDecimal mrpBigDecimal sellingPrice
}
common fields - a trait approach
Price groovyInActionToday = new Price(productCode: '9789351198260', mrp: 899, sellingPrice: 751,createdBy: 'admin',modifiedBy: 'rk')
println groovyInActionToday.createdByprintln groovyInActionToday.modifiedBy
Chainingtrait JuniorManager implements Manager {def approve(BigDecimal amount){if(amount < 10000G){ println "Approved by JM” }else{println "Sending to SM"super.approve()
}}
}trait SeniorManager implements Manager {def approve(BigDecimal amount){println "Approved by SM"
}}
Chaining
class FinanceDepartment implements SeniorManager, JuniorManager {}FinanceDepartment finance = new FinanceDepartment()finance.approve(3000)finance.approve(30000)