groovy 3 and the new groovy meta object protocol in examples

50
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 1 Groovy 3 the new Meta Object Protocol in examples Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Jochen Theodorou, GoPivtoal Germany GmbH @JochenTheodorou

Upload: gr8conf

Post on 17-May-2015

992 views

Category:

Technology


3 download

DESCRIPTION

Groovy3 and the new MOP are closing in! But the time of this talk the new MOP will not be done, but I will show some examples of how old Groovy code will look like transferred to the new MOP.

TRANSCRIPT

Page 1: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/1

Groovy 3 the new Meta Object Protocol

in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

Jochen Theodorou, GoPivtoal Germany GmbH@JochenTheodorou

Page 2: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/2

… in certainly not enough examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

Jochen Theodorou, GoPivtoal Germany GmbH@JochenTheodorou

Page 3: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/3

What cannot go forwardgoes backwards.

Johann Wolfgang von Goethe (1749-1832), German PoetTranslation by Jochen Theodorou

Page 4: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/4

Goals:

■ Metaclass as Persistent Collection and Realms

● Better multi threading performance

● Allowing different versions of metaclasses for same class

■ Only internal metaclasses

● no „extends MetaClassImpl“ any more, instead like ExpandoMetaClass for everything

● Delegation instead of Inheritance

■ MOP Methods

● Names and Signatures change to avoid conflicts with normal methods

● GroovyObject becomes a marker interface or is removed

● All methods then optional and in different variants

● No exception controlled MOP any more

■ Others

● All operators available for meta programmings

● Based on invokedynamic and ClassValue (Java 7 becomes minimum)

Page 5: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/5

MOP Methods= in class defined methods to control MOP

Page 6: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/6

Overview:

■ Uncached:

● Difficulty: I did hear of Groovy

● methodMissing, methodIntercept, propertyMissing, propertyIntercept

■ Cached 1:

● Difficulty: Me, want more. Now!

● cacheMethodMissing, cacheMethodIntercept, cachePropertyMissing,

cachePropertyIntercept

■ Cached 2:

● Difficulty: I know what I do! Give me the full program!

● cacheMethodTarget, cachePropertyTarget

Page 7: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/7

MOP Methods – A Groovy BuilderGroovy 1 and Groovy 2

Page 8: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/8

Groovy Builder in Groovy 1/2

class XmlBuilder { def out

def methodMissing(String name, args) { out << "<$name>" if(args[0] instanceof Closure) {

args[0].delegate = this args[0].call() } else {

out << args[0].toString() } out << "</$name>"

}}

def xml = new XmlBuilder(out:System.out) xml.html {

head { title "Hello World" }

body { p "Welcome!" }

}

console output:

<html><head><title>Hello World</title></head><body><p>Welcome!

</p></body></html>

Page 9: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/9

Groovy Builder in Groovy 1/2

class XmlBuilder { def out

def methodMissing(String name, args) { out << "<$name>" if(args[0] instanceof Closure) {

args[0].delegate = this args[0].call() } else {

out << args[0].toString() } out << "</$name>"

}}

def xml = new XmlBuilder(out:System.out) xml.html {

head { title "Hello World" }

body { p "Welcome!" }

}

console output:

<html><head><title>Hello World</title></head><body><p>Welcome!

</p></body></html>

called if no method can be found for call

Page 10: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/10

Groovy Builder in Groovy 1/2

class XmlBuilder { def out

def methodMissing(String name, args) { out << "<$name>" if(args[0] instanceof Closure) {

args[0].delegate = this args[0].call() } else {

out << args[0].toString() } out << "</$name>"

}}

def xml = new XmlBuilder(out:System.out) xml.html {

head { title "Hello World" }

body { p "Welcome!" }

}

console output:

<html><head><title>Hello World</title></head><body><p>Welcome!

</p></body></html>

name = name of callargs = arguments of call

Page 11: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/11

Groovy Builder in Groovy 1/2

class XmlBuilder { def out

def methodMissing(String name, args) { out << "<$name>" if(args[0] instanceof Closure) {

args[0].delegate = this args[0].call() } else {

out << args[0].toString() } out << "</$name>"

} //implcit return !//implcit return !}

def xml = new XmlBuilder(out:System.out) xml.html {

head { title "Hello World" }

body { p "Welcome!" }

}

console output:

<html><head><title>Hello World</title></head><body><p>Welcome!

</p></body></html>The result of the call is theresult of methodMissing

Page 12: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/12

MOP Methods – A Groovy BuilderGroovy 3 Uncached

Page 13: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/13

Groovy Builder in Groovy 3 - Uncachedclass XmlBuilder {

def out MopResult methodMissing(String name, args) { out << "<$name>" If (args[0] instanceof Closure) {

args[0].delegate = this args[0].call() } else {

out << args[0].toString() } out << "</$name>"

return MopResult.VOID } }

def xml = new XmlBuilder(out:System.out) xml.html { head {

title "Hello World" } body {

p "Welcome!" } }

Page 14: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/14

Groovy Builder uncached - before and after

class XmlBuilder { def out

def methodMissing (String name, args) { out << "<$name>"

if(args[0] instanceof Closure) { args[0].delegate = this args[0].call()

} else { out << args[0].toString() }

out << "</$name>" }}

class XmlBuilder {

def out MopResult methodMissing (String name, args) {

out << "<$name>" If (args[0] instanceof Closure) { args[0].delegate = this

args[0].call() } else { out << args[0].toString() }

out << "</$name>" return MopResult.VOID }

}

Page 15: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/15

Groovy Builder uncached - before and after

class XmlBuilder { def out

def methodMissing (String name, args) { out << "<$name>"

if(args[0] instanceof Closure) { args[0].delegate = this args[0].call()

} else { out << args[0].toString() }

out << "</$name>" }}

class XmlBuilder {

def out MopResult methodMissing (String name, args) {

out << "<$name>" If (args[0] instanceof Closure) { args[0].delegate = this

args[0].call() } else { out << args[0].toString() }

out << "</$name>" return MopResult.VOID }

}

MopResult contains theresult of the call

Page 16: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/16

Groovy Builder uncached - before and after

class XmlBuilder { def out

def methodMissing (String name, args) { out << "<$name>"

if(args[0] instanceof Closure) { args[0].delegate = this args[0].call()

} else { out << args[0].toString() }

out << "</$name>" }}

class XmlBuilder {

def out MopResult methodMissing (String name, args) {

out << "<$name>" If (args[0] instanceof Closure) { args[0].delegate = this

args[0].call() } else { out << args[0].toString() }

out << "</$name>" return MopResult.VOID }

}

it can also transport errorsor that there is no result (VOID)

Page 17: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/17

MOP Methods – A Groovy BuilderGroovy 3 Cached

return how to get a result, instead of the result itself

Page 18: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/18

Ein Groovy Builder in Groovy 3 - Cached

class XmlBuilder {

def out def methodMissing

(String name, args) {

out << "<$name>"

if(args[0] instanceof Closure) {

args[0].delegate = this

args[0].call()

} else { out << args[0].toString()

} out << "</$name>"

}

}

class XmlBuilder {

def out

void cacheMethodMissing (GroovyCall call, String name)

{ call.chain {out << "<${name}>"}

if(call[0].isAssignableTo(Closure))

{ call[0].chain

{it.delegate = this} call[0].execute()

} else {

call[0].execute "toString" }

call.chain {out << "</${name}>"} }

}

Page 19: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/19

Ein Groovy Builder in Groovy 3 - Cached

class XmlBuilder {

def out def methodMissing

(String name, args) {

out << "<$name>"

if(args[0] instanceof Closure) {

args[0].delegate = this

args[0].call()

} else { out << args[0].toString()

} out << "</$name>"

}

}

class XmlBuilder {

def out

void cacheMethodMissing (GroovyCall call, String name)

{ call.chain {out << "<${name}>"}

if(call[0].isAssignableTo(Closure))

{ call[0].chain

{it.delegate = this} call[0].execute()

} else {

call[0].execute "toString" }

call.chain {out << "</${name}>"} }

}

since there is no resultwe return void

Page 20: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/20

Ein Groovy Builder in Groovy 3 - Cached

class XmlBuilder {

def out def methodMissing

(String name, args) {

out << "<$name>"

if(args[0] instanceof Closure) {

args[0].delegate = this

args[0].call()

} else { out << args[0].toString()

} out << "</$name>"

}

}

class XmlBuilder {

def out

void cacheMethodMissing (GroovyCall call, String name)

{ call.chain {out << "<${name}>"}

if(call[0].isAssignableTo(Closure))

{ call[0].chain

{it.delegate = this} call[0].execute()

} else {

call[0].execute "toString" }

call.chain {out << "</${name}>"} }

}

GroovyCall is created foreach uncached call

Page 21: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/21

Ein Groovy Builder in Groovy 3 - Cached

class XmlBuilder {

def out def methodMissing

(String name, args) {

out << "<$name>"

if(args[0] instanceof Closure) {

args[0].delegate = this

args[0].call()

} else { out << args[0].toString()

} out << "</$name>"

}

}

class XmlBuilder {

def out

void cacheMethodMissing (GroovyCall call, String name)

{ call.chain {out << "<${name}>"}

if(call[0].isAssignableTo(Closure))

{ call[0].chain

{it.delegate = this} call[0].execute()

} else {

call[0].execute "toString" }

call.chain {out << "</${name}>"} }

}

No argument objects here,only their rutime classes

Page 22: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/22

Some more details:

■ We provide a high-level API to let you express how to get to a result, not what the

result is – This allows caching in the first place

■ The to be cached method called can go through cacheMethodMissing more than

once. Reasons for that can be type changes for the arguments or the receiver

■ If you want to react different to different values of the same type, caching might be

not for you. (example: provide the method to be called as additional argument

instead)

Page 23: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/23

MOP Methods – A Groovy BuilderGroovy 3 MethodHandles

Page 24: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/24

Ein Groovy Builder in Groovy 3 – MethodHandles class XmlBuilder {

def out

private final MethodHandle outField = LOOKUP.findGetter....

void cacheMethodTarget

(GroovyCall call, String name)

{

call.chain(

GroovyInvoker.bind(outField,"leftShift","<${name}>"))

if (call.arg(0).isAsignableTo(Closure)) {

call.arg(0).chain(

GroovyInvoker.setProperty("delegate",this))

call.arg(0).execute()

} else {

call.arg(0).execute "toString"

}

call.chain(

GroovyInvoker.bind(outField,"leftShift","</${name}>"))

}

}

Page 25: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/25

Some Explanations:

■ Target is to produce a MethodHandle

■ GroovyCall high-level API is helping you here and can be mixed with MethodHandles

■ Of course the MethodHandles-API from Java7 is efficient and powerful, but also

difficult to understand and handle – for example because types have to match

exactly

■ Ultimately (and only for the most crazy people) we want to provide a way to give

your own bootstrap method and then design yourself what you do with the call. This

way you could for example completely emulate Javalogik and also speed (of course

there is still an overhead through invokedynamic)

Page 26: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/26

MOP Methods – Dynamic FinderGroovy 1 und Groovy 2

Page 27: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/27

Dynamic Finder in Groovy 1/2

class GORM {

// an array of dynamic methods that use regex

def dynamicMethods = [...]

def methodMissing (String name, args) {

def method = dynamicMethods.find { it.match(name) }

if (method) {

GORM.metaClass."$name" = { Object[] varArgs ->

method.invoke(delegate, name, varArgs)

}

return method.invoke(delegate, name, args)

}

else throw new

MissingMethodException(name, delegate, args)

}

}

Page 28: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/28

Dynamic Finder in Groovy 1/2

class GORM {

// an array of dynamic methods that use regex

def dynamicMethods = [...]

def methodMissing (String name, args) {

def method = dynamicMethods.find { it.match(name) }

if (method) {

GORM.metaClass."$name" = { Object[] varArgs ->

method.invoke(delegate, name, varArgs)

}

return method.invoke(delegate, name, args)

}

else throw new

MissingMethodException(name, delegate, args)

}

}

adds a meta method to metaClassfor each missing method

Page 29: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/29

Dynamic Finder in Groovy 1/2

class GORM {

// an array of dynamic methods that use regex

def dynamicMethods = [...]

def methodMissing (String name, args) {

def method = dynamicMethods.find { it.match(name) }

if (method) {

GORM.metaClass."$name" = { Object[] varArgs ->

method.invoke(delegate, name, varArgs)

}

return method.invoke(delegate, name, args)

}

else throw new

MissingMethodException(name, delegate, args)

}

}

makes the metaClassstay in memory

Page 30: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/30

The metaclass is in Groovy 1 and 2 actually linked to an instance, but has to be

saved in a global structure. That might use SoftReferences to avoid memory

problems, still garbage collection doesn't like such actions.

Page 31: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/31

MOP Methods – Dynamic FinderGroovy 3 Uncached

Page 32: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/32

Dynamic Finder in Groovy 3

class GORM {

// an array of dynamic methods that use regex

def dynamicMethods = [...]

MopResult methodMissing (String name, args) {

def method = dynamicMethods.find { it.match(name) }

if (method) {

GORM.metaClass."$name" = { Object[] varArgs ->

method.invoke(delegate, name, varArgs)

}

return MopResult.of (GroovyInvoker.invoke

(method, delegate, name, args))

}

else return MopResult.ERROR

}

}

Page 33: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/33

Dynamic Finder in Groovy 3

class GORM {

// an array of dynamic methods that use regex

def dynamicMethods = [...]

MopResult methodMissing (String name, args) {

def method = dynamicMethods.find { it.match(name) }

if (method) {

GORM.metaClass."$name" = { Object[] varArgs ->

method.invoke(delegate, name, varArgs)

}

return MopResult.of (GroovyInvoker.invoke

(method, delegate, name, args))

}

else return MopResult.ERROR

}

}

makes the metaClassstay in memory

Page 34: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/34

Dynamic Finder in Groovy 3

class GORM {

// an array of dynamic methods that use regex

def dynamicMethods = [...]

MopResult methodMissing (String name, args) {

def method = dynamicMethods.find { it.match(name) }

if (method) {

GORM.metaClass."$name" = { Object[] varArgs ->

method.invoke(delegate, name, varArgs)

}

return MopResult.of (GroovyInvoker.invoke

(method, delegate, name, args))

}

else return MopResult.ERROR

}

}

but not longer than the class GORM

Page 35: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/35

MOP Methods – Dynamic FinderGroovy 3 Cached

Page 36: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/36

Dynamic Finder in Groovy 3

class GORM {

// an array of dynamic methods that use regex

def dynamicMethods = [...]

void cacheMethodMissing (GroovyCall call, String name)

{

def method = dynamicMethods.find { it.match(name) }

if (method) {

call.chain (method, delegate, name)

}

else call.error()

}

}

metaClass stays unchanged

Page 37: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/37

Metaclass Versions and Views

Page 38: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/38

Recover old version of a metaclass

class A{}

A.metaClass.foo = {->1}

assert new A().foo() == 1

def oldMetaClass = A.metaClass.freeze()

A.metaClass.foo = {->2}

assert new A().foo() == 2

oldMetaClass.restore()

assert new A().foo() == 1

Page 39: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/39

Recover old version of a metaclass

class A{}

A.metaClass.foo = {->1}

assert new A().foo() == 1

def oldMetaClass = A.metaClass.freeze()

A.metaClass.foo = {->2}

assert new A().foo() == 2

oldMetaClass.restore()

assert new A().foo() == 1

handler for the meta classInstead of the meta class itself

Page 40: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/40

Recover old version of a metaclass

class A{}

A.metaClass.foo = {->1}

assert new A().foo() == 1

def oldMetaClass = A.metaClass.freeze()

A.metaClass.foo = {->2}

assert new A().foo() == 2

oldMetaClass.restore()

assert new A().foo() == 1

make handler keepingcurrent meta class version

Page 41: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/41

Recover old version of a metaclass

class A{}

A.metaClass.foo = {->1}

assert new A().foo() == 1

def oldMetaClass = A.metaClass.freeze()

A.metaClass.foo = {->2}

assert new A().foo() == 2

oldMetaClass.restore()

assert new A().foo() == 1set meta method

Page 42: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/42

Recover old version of a metaclass

class A{}

A.metaClass.foo = {->1}

assert new A().foo() == 1

def oldMetaClass = A.metaClass.freeze()

A.metaClass.foo = {->2}

assert new A().foo() == 2

oldMetaClass.restore()

assert new A().foo() == 1

restore old metaclass version

Page 43: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/43

Some explanations:

■ Before Groovy 3 we always mutate the metaclass

● Recovering an old state is difficult

● Isolating changes almost impossible

■ In Groovy 3 the metaclass is a persistent collection which you can reference by a

handler

● Handler can be set to always give the actual meta class

● Or to “freeze” to keep the actual version and then maybe restore later

In the long term this might actually allow to serialize meta class states

Page 44: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/44

Usage of Realms

class A{}

A.metaClass.foo = {->1}

assert new A().foo() == 1

realm {

A.metaClass.foo = {->2}

assert new A().foo() == 2

}

assert new A().foo() == 1

Page 45: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/45

Usage of Realms

class A{}

A.metaClass.foo = {->1}

assert new A().foo() == 1

realm {

A.metaClass.foo = {->2}

assert new A().foo() == 2

}

assert new A().foo() == 1

create sub realm

Page 46: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/46

Usage of Realms

class A{}

A.metaClass.foo = {->1}

assert new A().foo() == 1

realm {

A.metaClass.foo = {->2}

assert new A().foo() == 2

}

assert new A().foo() == 1

set new meta method

Page 47: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/47

Usage of Realms

class A{}

A.metaClass.foo = {->1}

assert new A().foo() == 1

realm {

A.metaClass.foo = {->2}

assert new A().foo() == 2

}

assert new A().foo() == 1only visible in subrealm

Page 48: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/48

Usage of Realms

class A{}

A.metaClass.foo = {->1}

assert new A().foo() == 1

realm {

A.metaClass.foo = {->2}

assert new A().foo() == 2

} // end of realm

assert new A().foo() == 1

return to parent realm

Page 49: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/49

Some Explanations:

■ A Realm is a set of metaclases separated from the normal program (or parent realm)

at the point of call

■ Changes inside the Realm stay in the Realm and its subrealms

■ Exiting a Realm means to discard all changes done in the Realm

Thought Usage:

● Libraries can isolate code and protect it from outside changes

● Lexicographic Categories

Page 50: Groovy 3 and the new Groovy Meta Object Protocol in examples

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/50

And as always, there is by far not enough time

:(