Ext JS 2.0 リリース
Ext JS 2.0がついにリリースとなったようで。
getPropertyとsetProperty
getPropertyとsetProperty
Groovyでは、getPropertyという名前のメソッドをクラスに定義しておくと、プロパティから値を取得する際に呼ばれるようになります。また、setPropertyという名前のメソッドをクラスに定義しておくと、プロパティに値を設定する際に呼ばれるようになります。
[ソース] class MyClass { def greeting = 'accessed greeting directly' def properties = [:] Object getProperty( String property ) { println "read from property $property" properties[ property ] } void setProperty( String property, Object newValue ) { println "wrote to property $property" properties[ property ] = newValue } } def mine = new MyClass( ) println mine.greeting println '-----' mine.greeting= 'accessed message indirectly' println mine.greeting [実行結果] read from property greeting null
-
-
-
- -
-
-
実行結果からもわかるように、getPropertyとsetPropertyメソッド定義すると、定義済のプロパティへのアクセスはできなくなってしまいます。また、どちらかだけ定義するということもできます。
[ソース] class MyClass { def greeting = 'accessed greeting directly' def properties = [:] void setProperty( String property, Object newValue ) { println "wrote to property $property" properties[ property ] = newValue } } def mine = new MyClass( ) println mine.greeting println '-----' mine.greeting= 'accessed message indirectly' println mine.greeting [実行結果] accessed greeting directly
-
-
-
- -
-
-
.@
invokeMethodを定義した際に、".&"で定義済のメソッドを直接呼ぶことができましたが、プロパティの場合は、「"オブジェクト" ".@" "プロパティ"」という形式で呼び出すことで、定義済のプロパティに直接アクセスすることができます。
[ソース] class MyClass { def greeting = 'accessed greeting directly' def properties = [:] Object getProperty( String property ) { println "read from property $property" properties[ property ] } void setProperty( String property, Object newValue ) { println "wrote to property $property" properties[ property ] = newValue } } def mine = new MyClass( ) println mine.greeting println '-----' println mine.@greeting [実行結果] read from property greeting null
-
-
-
- -
-
-
".@"の形式でプロパティにアクセスする場合、未定義のプロパティであれば、MissingFieldExceptionが発生します。
[ソース] class MyClass { def greeting = 'accessed greeting directly' def properties = [:] Object getProperty( String property ) { println "read from property $property" properties[ property ] } void setProperty( String property, Object newValue ) { println "wrote to property $property" properties[ property ] = newValue } } def mine = new MyClass( ) println mine.greeting println '-----' println mine.message println '-----' println mine.@message [実行結果] read from property greeting null
-
-
-
- -
-
-
-
-
-
- -
-
-
invokeMethodとGroovyInterceptable
invokeMethod
Groovyでは、invokeMethodという名前のメソッドをクラスに定義しておくと、未定義のメソッドが呼ばれた際に呼ばれるようになります。
[ソース] class MyClass { def hello( ) { 'invoked hello directly' } def invokeMethod( String name, Object args ) { return "unknown method $name(${args.join(', ')})" } } def mine = new MyClass( ) println mine.hello( ) println mine.foo( "Mark", 19 ) [実行結果] invoked hello directly unknown method foo(Mark, 19)
上記の実行結果からもわかるとおり、定義済のメソッド呼び出しに対しては、invokeMethodが呼ばれることはありません。
GroovyInterceptable
GroovyInterceptableインタフェースを実装することにより、定義・未定義にかかわらず、すべてのメソッド呼び出しに対して、invokeMethodが呼ばれるようになります。
[ソース] class MyClass implements GroovyInterceptable { def hello( ) { 'invoked hello directly' } def invokeMethod( String name, Object args ) { return "unknown method $name(${args.join(', ')})" } } def mine = new MyClass( ) println mine.hello( ) println mine.foo( "Mark", 19 ) [実行結果] unknown method hello() unknown method foo(Mark, 19)
上記の実行結果からもわかるとおり、定義・未定義にかかわらず、常にinvokeMethodが呼ばれてしまいます。
.&
GroovyInterceptableインタフェースを実装した際、メソッド呼び出し時に、「"オブジェクト" "." "メソッド"」という形式ではなく、「"オブジェクト" ".&" "メソッド"」という形式で呼び出すことで、定義済のメソッドを呼び出すことができます。
[ソース] class MyClass implements GroovyInterceptable { def hello( ) { 'invoked hello directly' } def invokeMethod( String name, Object args ) { return "unknown method $name(${args.join(', ')})" } } def mine = new MyClass( ) println mine.&hello( ) println mine.foo( "Mark", 19 ) [実行結果] invoked hello directly unknown method foo(Mark, 19)
ただし、未定義のメソッドを".&"の形式で呼び出すと、上のソース例ではMissingMethodExceptionが発生します。
[ソース] class MyClass implements GroovyInterceptable { def hello( ) { 'invoked hello directly' } def invokeMethod( String name, Object args ) { return "unknown method $name(${args.join(', ')})" } } def mine = new MyClass( ) println mine.&hello( ) println mine.&foo( "Mark", 19 ) [実行結果] invoked hello directly Exception thrown: groovy.lang.MissingMethodException: No signature of method: MyClass.foo() is applicable for argument types: (java.lang.String, java.lang.Integer) values: {"Mark", 19}
".&"と".@"の、文字列の変数展開によるアクセス
".&"による定義済メソッドへのアクセス、および".@"による定義済プロパティへのアクセスは、文字列の変数展開と組み合わせると、より柔軟なアクセスが可能になります。
[ソース] class MyClass implements GroovyInterceptable { def greeting = 'accessed greeting' def id = 'White: ' Object getProperty( String property ) { try{ return this.@id + // プロパティへの直接的なアクセス 'indirectly ' + this.@"$property" // プロパティへの直接的で動的なアクセス } catch( e ) { return "no such property $property" } } def hello( Object[] args ) { "invoked hello with (${args.join(', ')})" } def id( ) { 'Green: ' } def invokeMethod( String name, Object args ) { try{ return this.&id( ) + // 直接的なメソッド呼び出し 'indirectly ' + this.&"$name"( args ) // 直接的で動的なメソッド呼び出し } catch( e ) { return "no such method $name" } } } def mine = new MyClass( ) println mine.greeting println mine.farewell println mine.hello( 1, 'b', 3 ) println mine.foo( 'Mark', 19 ) [実行結果] White: indirectly accessed greeting no such property farewell Green: indirectly invoked hello with (1, b, 3) no such method foo