Last active
August 29, 2015 13:58
-
-
Save nobeans/10127510 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// helper | |
def shouldFail(Class klass, Closure clos) { | |
try { | |
clos.call() | |
} catch (Throwable e) { | |
assert e.class == klass : "expected: ${klass.name}, but actual: ${e.class.name}" | |
return | |
} | |
assert false : "expected: ${klass.name}, but nothing thrown" | |
} | |
// traitとクラスの定義 | |
trait Flyable { | |
String name = "trait" | |
String fly() { "I'm $name and flying!" } | |
} | |
class Bird implements Flyable { | |
} | |
class UFO { | |
} | |
// 普通に静的にtraitを適用する | |
def b = new Bird() | |
assert b.fly() == "I'm trait and flying!" | |
b.name = "bird" | |
assert b.fly() == "I'm bird and flying!" | |
// 実行時にtraitを適用する | |
def ufo = new UFO() | |
def ufoF = ufo as Flyable | |
assert ufoF.fly() == "I'm trait and flying!" | |
ufoF.name = "UFO" | |
assert ufoF.fly() == "I'm UFO and flying!" | |
shouldFail(MissingMethodException) { | |
// もちろん元オブジェクトには影響ない | |
ufo.fly() | |
} | |
// 元クラスに対するProxyクラスが作られてるみたい。 | |
assert ufo.class != ufoF.class | |
assert ufoF.class.name ==~ /UFO[0-9]+_groovyProxy/ | |
// -> "UFO<通番>_groovyProxy"のようなクラス名が生成されている | |
// 通番部部分は、同一JVM上で実行するたびにインクリメントされてる風 | |
// 実行時適用するたびに新たなインスタンスが生成される。 | |
def temp = [] | |
temp << (ufo as Flyable) | |
temp << (ufo as Flyable) | |
temp << (ufo as Flyable) | |
assert temp.unique().size() == 3 | |
temp*.dump().each { println it } | |
// <UFO55_groovyProxy@5ef0c85a $closures$delegate$map=[:] $delegate=UFO@464e19f6 Flyable__name=null> | |
// <UFO55_groovyProxy@4c2c5287 $closures$delegate$map=[:] $delegate=UFO@464e19f6 Flyable__name=null> | |
// <UFO55_groovyProxy@7083dc29 $closures$delegate$map=[:] $delegate=UFO@464e19f6 Flyable__name=null> | |
// プロキシクラスに対してメタクラスをいじっても、当然元のクラス/インスタンスには影響しない | |
ufoF.metaClass.hoge = {-> println "HOGE" } | |
ufoF.hoge() | |
shouldFail(MissingMethodException) { | |
ufo.hoge() | |
} | |
// $delegateプロパティで変換前のオブジェクトを参照できる。 | |
// 元のオブジェクトとの同一性判定がどうしても必要な場合も一応どうにかできる。 | |
assert ufoF.$delegate == ufo | |
shouldFail(ReadOnlyPropertyException) { | |
// $delegateはReadOnlyプロパティ | |
ufoF.$delegate = "" | |
} | |
// Proxyオブジェクト経由だと自分自身のメソッドへの呼び出しはProxyの仕組みを通らないのでNGになったりする実装もあるけど大丈夫? | |
trait ChainCall { | |
def a() { b() } | |
def b() { c() } | |
def c() { d() } | |
} | |
class ChainCallClass1 implements ChainCall { | |
def d() { "Goal!" } | |
} | |
class ChainCallClass2 { | |
def d() { "Goal!" } | |
} | |
assert new ChainCallClass1().a() == "Goal!" | |
assert (new ChainCallClass2() as ChainCall).a() == "Goal!" | |
// ->大丈夫 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment