glbpkpq7skovivl4nfgl...
TRANSCRIPT
![Page 1: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/1.jpg)
MetaProgrammingWith
Groovy
Presentation by: Ali and Gaurav
![Page 2: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/2.jpg)
Agenda
▣ Groovy Is Dynamic▣ What is MetaProgramming?▣ Runtime MetaProgramming
□ What is MOP?□ Understanding Groovy□ Meta Class
▣ Intercepting Methods Using MOP□ InvokeMethod□ GroovyInterceptable□ Intercepting Methods using MetaClass
▣ MOP Method Injection□ MetaClass□ Categories□ Mixins/Traits
![Page 3: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/3.jpg)
Agenda (continues..)
▣ MOP Method Synthesis▣ MOP Class Synthesis▣ Compile-time MetaProgramming
□ AST and Compilation□ Groovy AST Transformation□ Global AST Transformation□ Local AST Transformation
▣ Why we should use MetaProgramming?▣ References
![Page 4: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/4.jpg)
Groovy Is Dynamic
▣Groovy allows "Delay" to runtime some checks/decisions that are usually performed during the compilation.
▣Add properties/behaviours in runtime.▣Wide range of applicability
□DSLs□Builders□Advanced logging, tracing, debugging & profiling□Allow organize the codebase better
That's why we can talk about Metaprogramming in Groovy.
![Page 5: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/5.jpg)
What isMetaProgramming
?
![Page 6: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/6.jpg)
‘’Metaprogramming is the writing of computer programs that write or manipulate other programs (or themselves) as their data.
- Wikipedia
![Page 7: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/7.jpg)
Overview
The Groovy language supports two flavors of metaprogramming:
▣Runtime metaprogramming, and▣Compile-time metaprogramming.
The first one allows altering the class model and the behavior of a program at runtime, while the second only occurs at compile-time.
![Page 8: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/8.jpg)
RuntimeMetaProgramming
![Page 9: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/9.jpg)
Runtime MetaProgramming
▣Groovy provides this through Meta-Object Protocol (MOP).
▣We can use MOP to:□Invoke methods dynamically□Synthesize classes and methods on the fly.
With runtime metaprogramming we can postpone to runtime the decision to intercept, inject and even synthesize methods of classes and interfaces.
![Page 10: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/10.jpg)
What is the Meta Object Protocol?
![Page 11: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/11.jpg)
Understanding Groovy
For a deep understanding of Groovy MOP we first need to understand Groovy objects and Groovy’s method handling. In Groovy, we work with three kinds of objects:
▣POJO,▣POGO, and▣Groovy Interceptors
So, for each object Groovy allows metaprogramming but in different manner.
![Page 12: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/12.jpg)
continues...
▣ POJO - A regular Java object, whose class can be written in Java or any other language for the JVM.
▣ POGO - A Groovy object, whose class is written in Groovy. It extends java.lang.Object and implements the groovy.lang.GroovyObject interface by default.
▣ Groovy Interceptor - A Groovy object that implements the groovy.lang.GroovyInterceptable interface and has method-interception capability, which we’ll discuss in the GroovyInterceptable section.
For every method call Groovy checks whether the object is a POJO or a POGO. For POJOs, Groovy fetches it’s MetaClass from the groovy.lang.MetaClassRegistry and delegates method invocation to it.
![Page 13: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/13.jpg)
continues...
For POGOs, Groovy takes more steps, as illustrated below:
![Page 14: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/14.jpg)
Meta Class
▣MetaClass registry for each class.▣Collection of methods/properties.▣We can always modify the metaclass.
![Page 15: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/15.jpg)
Intercepting Methods Using
MOP
![Page 16: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/16.jpg)
Groovy Object Interface
GroovyObject has a default implementation in the groovy.lang.GroovyObjectSupport class and it is responsible to transfer invocation to the groovy.lang.MetaClass object. The GroovyObject source looks like this:
package groovy.lang;
public interface GroovyObject {
Object invokeMethod(String name, Object args);
Object getProperty(String propertyName);
void setProperty(String propertyName, Object newValue);
MetaClass getMetaClass();
void setMetaClass(MetaClass metaClass);}
![Page 17: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/17.jpg)
1.invokeMethod
![Page 18: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/18.jpg)
invokeMethod
This invokeMethod is called when the method you called is not present on a Groovy object. Example:
class InvokeMethodDemo { def invokeMethod(String name, Object args) { return "called invokeMethod $name $args" }
def test() { return 'method exists' }}
def invokeMethodDemo = new InvokeMethodDemo()assert invokeMethodDemo.test() == 'method exists'assert invokeMethodDemo.hello() == 'called invokeMethod hello []'
![Page 19: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/19.jpg)
2.GroovyInterceptab
le
![Page 20: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/20.jpg)
GroovyInterceptable
▣ Classes compiled by Groovy implements GroovyObject interface.
▣ We can implement GroovyInterceptable to hook into the execution process.
package groovy.lang;
public interface GroovyInterceptable extends GroovyObject {}
When a Groovy object implements the GroovyInterceptable interface, it’s invokeMethod() is called for any method calls.
![Page 21: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/21.jpg)
GroovyInterceptable Example
class InterceptionDemo implements GroovyInterceptable { def definedMethod() {}
def invokeMethod(String name, Object args) { "$name invokedMethod" }}
def interceptionDemo = new InterceptionDemo()assert interceptionDemo.definedMethod() == 'definedMethod invokedMethod'assert interceptionDemo.someMethod() == 'someMethod invokedMethod'
![Page 22: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/22.jpg)
3.Intercepting
Methods Using MetaClass
![Page 23: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/23.jpg)
Intercepting Methods using MetaClass
If we want to intercept all methods call but do not want to implement the GroovyInterceptable interface we can implement invokeMethod() on an object’s MetaClass.
▣ Groovy maintains a meta class of type MetaClass for each class.
▣ Maintains a collection of all methods and properties of A.
▣ If we can't modify the class source code or if it's a Java class we can modify the meta-class.
▣ We can intercept methods by implementing the invokeMethod() method on the MetaClass.
![Page 24: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/24.jpg)
MetaClass Example
class InterceptionThroughMetaClassDemo { void sayHello(String name) { println "========> Hello $name" }}
InterceptionThroughMetaClassDemo.metaClass.invokeMethod = { String methodName, Object args ->
println("Invoking method '$methodName' with args '$args'") def method = InterceptionThroughMetaClassDemo.metaClass.getMetaMethod(methodName, args) method?.invoke(delegate, args)}
def demo = new InterceptionThroughMetaClassDemo()demo.sayHello("ALI")demo.sayHI("EVERYONE")demo.anotherMethod()
![Page 25: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/25.jpg)
MOP Method Injection
![Page 26: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/26.jpg)
MOP Method Injection
▣In Groovy we can “open” a class at any time.▣Injecting methods at code-writing time; we
know the names of methods we want to add.▣Different techniques:
□MetaClass□Categories□Extensions□Mixins / Traits
![Page 27: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/27.jpg)
1.MetaClass
![Page 28: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/28.jpg)
Types of MetaClass
▣ MetaClassImpl: Default meta class, it's used in the vast majority of case.
▣ ExpandoMetaClass: allow the addition or replacement of methods, properties and constructors on the fly.
▣ Other meta classes used internally and for testing.
Note: This is only true for Groovy.▣ In Grails all MetaClass are ExpandoMetaClass.
![Page 29: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/29.jpg)
Adding Methods Using MetaClass
class StringUtils { static String truncate(String text, Integer length, Boolean overflow = false) { text.take(length) + (overflow ? '...' : '') }}String chuckIpsum = "If you can see Chuck Norris, he can see you.\If you can not see Chuck Norris you may be only seconds away from death"
println StringUtils.truncate(chuckIpsum, 72)println StringUtils.truncate(chuckIpsum, 72, true)
String.metaClass.truncateDemo = { Integer length, Boolean overflow = false -> println "truncate string upto length $length" delegate.take(length) + (overflow ? '...' : '')}assert chuckIpsum.truncateDemo(20, true) == StringUtils.truncate(chuckIpsum, 20, true)
![Page 30: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/30.jpg)
Adding Properties Using MetaClass
class Utils {}
def utilsInstance = new Utils()
Utils.metaClass.version = "3.0"utilsInstance.metaClass.released = true
assert utilsInstance.version == "3.0"assert utilsInstance.released == trueprintln("utilsInstance.version: $utilsInstance.version")println("utilsInstance.released: $utilsInstance.released")
![Page 31: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/31.jpg)
Continues.. (Example 2)
class ExpandoLite {
protected dynamicPropMap = [:]
void setProperty(String propName, val) { dynamicPropMap[propName] = val }
def getProperty(String propName) { dynamicPropMap[propName] }}
class ExpandoLiteSpec extends Specification {
void 'test property access'() { given: def ex = new ExpandoLite()
when: ex.companyName = 'Nexthoughts'
then: 'Nexthoughts' == ex.companyName }}
![Page 32: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/32.jpg)
Adding Constructors Using MetaClass
try { println(new Integer(Calendar.instance))}catch (e) {}
Integer.metaClass.constructor << { Calendar calendar -> new Integer(calendar.get(Calendar.DATE))}println("Today's Date: ${new Integer(Calendar.instance)}")
![Page 33: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/33.jpg)
Overriding Methods Using MetaClass
// Integerassert '15' == 15.toString()Integer.metaClass.toString = { delegate == 15 ? 'The answer to life, the universe and everything' : String.valueOf(delegate)}
assert 15.toString() == 'The answer to life, the universe and everything'assert 100.toString() == '100'println("15.toString(): ${15.toString()}")println("100.toString(): ${100.toString()}")
// Booleanassert false.toBoolean() == falseBoolean.metaClass.toBoolean = { !delegate }
assert false.toBoolean() == trueprintln("false.toBoolean(): ${false.toBoolean()}")
![Page 34: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/34.jpg)
2.Categories
![Page 35: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/35.jpg)
Categories
▣Changes made to a MetaClass are “persistent” and hard to revert.
▣Categories are useful to change the meta class in a confined small piece of code.
▣A category can alter a class’ MetaClass.▣The MOP is modified in the closure and after
the closure execution, it resets to its old state.▣Category classes are not special.
![Page 36: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/36.jpg)
Continues.. (Example 1)
class StringUtils { static String truncate(String text, Integer length, Boolean overflow = false) { text.take(length) + (overflow ? '...' : '') }}
use(StringUtils) { println "Hello! Everyone.".truncate(5)}try { println "Hi! Ali.".truncate(5)} catch (MissingMethodException mme) { println mme}
![Page 37: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/37.jpg)
Continues.. (Example 2)
class Distance { def number
String toString() { println("==========> ${number}") "${number}" }}
@Category(Number)class NumberCategory { Distance getMeters() { new Distance(number: this + 'm') }
Distance getKiloMeters() { new Distance(number: this + 'km') }}
use(NumberCategory) { assert 10.kiloMeters.toString() == '10km' assert 50.meters.toString() == '50m'}
![Page 38: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/38.jpg)
3.Mixins / Traits
![Page 39: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/39.jpg)
Mixins
▣A mixin allow “bring in” or “mix in” implementations from multiple classes.
▣Groovy first call the mixed-in class.▣Mix multiple classes. The last added mixin
takes precedence.▣Override a method of a previous Mixin but not
methods in the meta class.▣Mixins cannot easily be un-done.
![Page 40: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/40.jpg)
continues..
class SpidermanPower { String spiderSense() { "Using spider-sense..." }}
class SupermanPower { String fly() { "Flying..." }}
@Mixin([SpidermanPower])class Person {}
def person = new Person()assert person.spiderSense() == "Using spider-sense..."
assert !(person instanceof SpidermanPower)
Person.mixin SupermanPower
assert person.fly() == "Flying..."assert !(person instanceof SupermanPower)
![Page 41: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/41.jpg)
continues..
class SpidermanPower { String spiderSense() { "Using spider-sense..." }}
class SupermanPower { String fly() { "Flying..." }}
@Mixin([SpidermanPower])class Person {}
def person = new Person()assert person.spiderSense() == "Using spider-sense..."
assert !(person instanceof SpidermanPower)
Person.mixin SupermanPower
assert person.fly() == "Flying..."assert !(person instanceof SupermanPower)
![Page 42: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/42.jpg)
‘’When we started fixing mixin bugs we didn't know if they were a bug or a feature, so we removed mixins and add traits.
- Jochen Theodorou
![Page 43: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/43.jpg)
▣Groovy 2.3+▣Similar to Java 8 default methods▣Supported in JDK 6, 7 and 8▣Stateful▣Composition over inheritance▣Documentation
Traits
Note - Link to Groovy Traits PPT
![Page 44: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/44.jpg)
Traits Example
trait SpidermanPower { String spiderSense() { "Using spider-sense..." }}
class Person implements SpidermanPower {}
def person = new Person()assert person.spiderSense() == "Using spider-sense..."println("=====> person.spiderSense(): ${person.spiderSense()}")assert person instanceof SpidermanPowerdef person2 = person.withTraits SupermanPowerassert person2.fly() == "Flying..."println("=====> person2.fly(): ${person2.fly()}")assert person2 instanceof SupermanPower
trait SupermanPower { String fly() { "Flying..." }}
![Page 45: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/45.jpg)
MOP Method Synthesis
![Page 46: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/46.jpg)
MOP Method Synthesis
▣Dynamically figure out the behaviour for methods upon invocation.
▣A synthesized method may not exist as a separate method until we call it.
▣invokeMethod, methodMissing and propertyMissing.
▣“Intercept, Cache, Invoke” pattern.
![Page 47: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/47.jpg)
Check for Methods and Properties
class Person { String name Integer age
String sayHi() { "Hi, my name is ${name} and I'm ${age}" }
String sayHiTo(String name) { "Hi ${name}, how are you?" }}
def p = new Person(name: 'Superman', age: 34)
assert p.respondsTo('sayHi')assert p.respondsTo('sayHiTo', String)assert !p.respondsTo('goodbye')
assert p.hasProperty('name')assert !p.hasProperty('country')
![Page 48: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/48.jpg)
Method Delegation
cl = { -> append "Hi!" append " this is closure delegate demo."}
sb = new StringBuffer()cl.delegate = sb
cl()println "SB: ${sb}"
![Page 49: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/49.jpg)
Continues.. (Example 2)
class ClosureDemo { void append(String arg) { println("append called with: ${arg}") }
void doit() { def cl = { append 'MetaProgramming Demo by' append ' Ali and Gaurav' } def sb = new StringBuffer() cl.delegate = sb cl() println("SB: ${sb}") }
static void main(args) { new ClosureDemo().doit() }}
![Page 50: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/50.jpg)
MOP Class Synthesis
![Page 51: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/51.jpg)
Creating Dynamic Classes with Expando
carA = new Expando()carB = new Expando(year: 2012, miles: 0)carA.year = 2012carA.miles = 10println "carA: " + carAprintln "carB: " + carB
In Groovy we can create a class entirely at runtime. The Groovy Expando class gives us the ability to synthesize classes dynamically.It got its name because it is dynamically expandable. We can assign properties and methods to it either at construction time using a Map or at any time dynamically.
car = new Expando(year: 2012, miles: 0, turn: { println 'turning...' })car.drive = { miles += 10 println "$miles miles driven"}car.drive()car.turn()
![Page 52: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/52.jpg)
Compile-timeMetaProgramming
?
![Page 53: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/53.jpg)
Compile-time MetaProgramming
▣Advanced feature.▣Analyze and modify a program’s structure at
compile time.▣Cross-cutting features:▣Inspect classes for thread safety▣Log messages▣Perform pre and postcheck operations all
without explicitly modifying the source code.▣We write code that generates bytecode or
gets involved during the bytecode generation.
![Page 54: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/54.jpg)
AST and Compilation
▣AST: Abstract Syntax Tree▣During compilation the AST is transformed▣Hook into different phases to change the final
byte-code.▣Initialization, Parsing, Conversion, Semantic
analysis, Canonicalization, Instruction selection, Class generation, Output, Finalization.
![Page 55: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/55.jpg)
Groovy AST Transformations
▣Groovy provides out-of-the-box a lot of AST Transformations
▣@EqualsAndHashCode, @ToString, @TuppleConstructor, @Canonical, @Grab, @Immutable, @Delegate, @Singleton, @Category, @Log4j, @CompileStatic, @TypeChecked, @Synchronized, etc.
![Page 56: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/56.jpg)
Global AST Transformations
▣There's no need to annotate anything.▣Applied to every single source unit during
compilation.▣Can be applied to any phase in the
compilation.▣Need a metadata file into the JAR file▣(META-INF/services/
org.codehaus.groovy.transform.ASTTransformation)
▣Grails uses Global Transformations intensively for example in GORM.
![Page 57: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/57.jpg)
Local AST Transformations
▣Annotate the code and only applied to that code.
▣Easy to debug.▣No need to create metadata file in a jar.▣Steps: Define an interface, Define the AST
transformation, Enjoy!
![Page 58: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/58.jpg)
Why we should use
MetaProgramming?
![Page 59: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/59.jpg)
Concept Review
▣Metaprogramming Easy and very out-of-the box
▣Easy and very powerful▣Write better code▣Add Behaviour easily▣Take advantage of this power because
Groovy, it’s Groovy
![Page 60: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/60.jpg)
References
▣ http://groovy-lang.org/metaprogramming.html▣ http://www.slideshare.net/ilopmar/metaprogramming-w
ith-groovy▣ http://www.slideshare.net/ilopmar/gr8conf-2016-metapr
ogramming-with-groovy
![Page 61: Glbpkpq7skovivl4nfgl signature-33b1641e302083be79596ecc3c545b41472c4ed11086a119b5d669225bd1b02e-poli-160730195348](https://reader035.vdocuments.pub/reader035/viewer/2022070514/587dee751a28abab7e8b4703/html5/thumbnails/61.jpg)
Thanks!Any questions?
You can find us at -▣ [email protected]▣ [email protected]
You can find demo code used with this presentation at -https://github.com/NexThoughts/groovyMetaProgramming