to Java 8 interface default methods • Elegant way to compose behavior • multiple inheritance, without the « diamond problem » • Traits can also be stateful • traits can have properties like normal classes • Compatible with static typing & compilation • class methods coming from traits are also visible from Java • Also possible to implement traits at runtime
"I'm flying!" } } ! class Bird implements FlyingAbility {} def b = new Bird() ! assert b.fly() == "I'm flying!" Traits: a simple example « trait », a new keyword for a new concept
"I'm flying!" } } ! class Bird implements FlyingAbility {} def b = new Bird() ! assert b.fly() == "I'm flying!" Traits: a simple example a class « implements » a trait
"I'm flying!" } } ! class Bird implements FlyingAbility {} def b = new Bird() ! assert b.fly() == "I'm flying!" Traits: a simple example the fly() method from the trait is available
! trait WebSurfer { String surf() { 'web' } } ! class Person { String name } ! class Hipster extends Person implements KiteSurfer, WebSurfer {} ! def h = new Hipster() assert h.surf() == 'web' Traits: what about conflicts?
! trait WebSurfer { String surf() { 'web' } } ! class Person { String name } ! class Hipster extends Person implements KiteSurfer, WebSurfer {} ! def h = new Hipster() assert h.surf() == 'web' Traits: what about conflicts? two surf() methods
! trait WebSurfer { String surf() { 'web' } } ! class Person { String name } ! class Hipster extends Person implements KiteSurfer, WebSurfer {} ! def h = new Hipster() assert h.surf() == 'web' Traits: what about conflicts?
! trait WebSurfer { String surf() { 'web' } } ! class Person { String name } ! class Hipster extends Person implements KiteSurfer, WebSurfer {} ! def h = new Hipster() assert h.surf() == 'web' Traits: what about conflicts? extending a class and implementing the two traits
! trait WebSurfer { String surf() { 'web' } } ! class Person { String name } ! class Hipster extends Person implements KiteSurfer, WebSurfer {} ! def h = new Hipster() assert h.surf() == 'web' Traits: what about conflicts?
! trait WebSurfer { String surf() { 'web' } } ! class Person { String name } ! class Hipster extends Person implements KiteSurfer, WebSurfer {} ! def h = new Hipster() assert h.surf() == 'web' Traits: what about conflicts? last declared trait wins!
! trait WebSurfer { String surf() { 'web' } } ! class Person { String name } ! class Hipster extends Person implements KiteSurfer, WebSurfer {} ! def h = new Hipster() assert h.surf() == 'web' Traits: what about conflicts?
! trait WebSurfer { String surf() { 'web' } } ! class Person { String name } ! class Hipster extends Person implements WebSurfer, KiteSurfer {} ! def h = new Hipster() assert h.surf() == 'kite' Traits: what about conflicts?
! trait WebSurfer { String surf() { 'web' } } ! class Person { String name } ! class Hipster extends Person implements WebSurfer, KiteSurfer {} ! def h = new Hipster() assert h.surf() == 'kite' Traits: what about conflicts? reverse the order!
! trait WebSurfer { String surf() { 'web' } } ! class Person { String name } ! class Hipster extends Person implements WebSurfer, KiteSurfer {} ! def h = new Hipster() assert h.surf() == 'kite' Traits: what about conflicts?
! trait WebSurfer { String surf() { 'web' } } ! class Person { String name } ! class Hipster extends Person implements WebSurfer, KiteSurfer { String surf() { KiteSurfer.super.surf() } } ! def h = new Hipster() assert h.surf() == 'kite' Traits: what about conflicts? Be explicit! Override surf() & use ‘super’
! trait WebSurfer { String surf() { 'web' } } ! class Person { String name } ! class Hipster extends Person implements WebSurfer, KiteSurfer { String surf() { KiteSurfer.super.surf() } } ! def h = new Hipster() assert h.surf() == 'kite' Traits: what about conflicts? Your class method takes precedence over the traits
} ! class Animal {} class NamedAnimal implements Named {} ! def na = new NamedAnimal(name: 'Felix') ! assert na.name == 'Felix' Traits: runtime implementation
} ! class Animal {} class NamedAnimal implements Named {} ! def na = new NamedAnimal(name: 'Felix') ! assert na.name == 'Felix' Traits: runtime implementation Somewhat artificial to have to create an intermediary class to get named animals
} ! class Animal {} class NamedAnimal implements Named {} ! def na = new NamedAnimal(name: 'Felix') ! assert na.name == 'Felix' Traits: runtime implementation
n, accu = 1G) { if (n < 2) accu else fact(n -‐ 1, n * accu) } ! assert fact(1000) > 10e2566 Downside of tail recursion is you might have to rewrite your algo to be tailrec friendly
int meaningOfLife = 42 } @BaseScript(CustomBase) import groovy.transform.BaseScript ! assert meaningOfLife == 42 You can add your own base methods and properties to all compiled scripts
int meaningOfLife = 42 } @BaseScript(CustomBase) import groovy.transform.BaseScript ! assert meaningOfLife == 42 Define the base script class for this script
int meaningOfLife = 42 } @BaseScript(CustomBase) import groovy.transform.BaseScript ! assert meaningOfLife == 42 In 2.3, ability to put the annotation on imports & package
File retrofitted on Path as well path.withReader { Reader r -‐> ... } path.eachLine { String line -‐> ... } path.eachFileRecurse { Path p -‐> ... } path << 'some content' path << bytes path.readLines() … Feature request to add all the java.nio.file.Files static utility methods as GDK
support for speed & efficiency • parser forked off the Boon JSON project • serializer carefully fine-tuned ! • Article on the parsing speed improvements • http://rick-hightower.blogspot.fr/2014/04/groovy-and-boon-provide-fastest-json.html
support for speed & efficiency • parser forked off the Boon JSON project • serializer carefully fine-tuned ! • Article on the parsing speed improvements • http://rick-hightower.blogspot.fr/2014/04/groovy-and-boon-provide-fastest-json.html
support for speed & efficiency • parser forked off the Boon JSON project • serializer carefully fine-tuned ! • Article on the parsing speed improvements • http://rick-hightower.blogspot.fr/2014/04/groovy-and-boon-provide-fastest-json.html Benchmark gives 3x to 4x performance factor over Jackson and GSON
support for speed & efficiency • parser forked off the Boon JSON project • serializer carefully fine-tuned ! • Article on the parsing speed improvements • http://rick-hightower.blogspot.fr/2014/04/groovy-and-boon-provide-fastest-json.html
! • Additional parsing modes: • INDEX_OVERLAY: super fast for <2MB payloads • using a « parsing overlay » technique • CHARACTER_SOURCE: for >2MB payloads • implemented with sliding windows over readers • LAX: beyond the JSON spec, nice for configuration files • support single quotes, / and # comments • CHAR_BUFFER: general purpose
« builders » • and particularly the MarkupBuilder class for generating arbitrary XML / HTML payloads • Compiled statically for fast template rendering • Internationalization aware •provide the desired Locale in the configuration object •usual suffix notation template_fr_FR.tpl • Custom base template class •ability to provide reusable methods across your templates
cars.each { car(make: it.make, name: it.name) } } model = [cars: [! new Car(make: 'Peugeot', name: '508'), ! new Car(make: 'Toyota', name: 'Prius’)! ]] Feed a model into your template
use createTypeCheckedModelTemplate() instead of createTemplate() • Advantages • get compilation errors • if a variable is not available • if you make mistakes in the code snippets • even faster templates
JDK 7+ invoke dynamic • get Java-like performance even for dynamic code • Rationalize the sedimentation of meta- programming • more coherence, less corner cases & inconsistencies • Provide a notion of « realm » • shield users of « monkey patching » • finer-grained control of meta-programming reach • Private visibility anyone?
v2! • but version 3 and 4 are out • Groovy’s grammar evolved from a Java grammar • harder to fix and evolve, especially with Antlr v2 • Advantages • Start from a clean slate • Antlr 4 more tolerant and powerful regarding ambiguities • Time to clean some grammar & syntax warts! • Need to implement the Java 8 constructs!
v2! • but version 3 and 4 are out • Groovy’s grammar evolved from a Java grammar • harder to fix and evolve, especially with Antlr v2 • Advantages • Start from a clean slate • Antlr 4 more tolerant and powerful regarding ambiguities • Time to clean some grammar & syntax warts! • Need to implement the Java 8 constructs! A « Google Summer of Code » student to help
support • to keep saying Groovy / Java interoperability is awesome! • New in Java 8 • lambdas • method references • default methods in interfaces • stream API, date / time API • annotations on types & repeated annotations
support • to keep saying Groovy / Java interoperability is awesome! • New in Java 8 • lambdas • method references • default methods in interfaces • stream API, date / time API • annotations on types & repeated annotations Groovy had already: closures, method pointers, mixins, enriched collection & time APIs
• http://www.flickr.com/photos/22914687@N05/4957591422/sizes/l/ • Sous la Tour Eiffel — By-Nc-Sa • http://www.flickr.com/photos/stewiedewie/244850735/sizes/l/in/photostream/ • Sous le pont — By-Nc-Nd • http://www.landscape-photo.net/displayimage.php?pid=5194 • Paris Metro - By-Nc-Sa • http://www.flickr.com/photos/22914687@N05/6317047263/sizes/l/