37

Groovyのスコープルールについて質問があります。次のスニペットでは、3つの変数がaあり、ローカルスコープがあり、bスクリプトスコープがあり、アノテーションcを使用してスクリプトスコープも取得する必要があります。@Field

#!/usr/bin/groovy
import groovy.transform.Field;

//println org.codehaus.groovy.runtime.InvokerHelper.getVersion()

def a = 42;
b = "Tea"
@Field def c = "Cheese"

void func()
{
    // println a // MissingPropertyException
    println b // prints "Tea"
    println c // prints "Cheese" with groovy 2.1.2, MissingPropertyException with groovy 1.8.6

}

class Main
{
    def method()
    {
        // println a // MissingPropertyException
        // println b // MissingPropertyException
        // println c // MissingPropertyException with both 1.8.6. and 2.1.2
    }

}

func();
new Main().method();

MissingPropertyExceptionコメントで示された行にsが表示されます。aその変数はローカルスコープを持っているため、上の例外が予想されます。bしかし、私は内部でアクセス可能であることを期待しますmethod()-そうではありません。 @Fieldgroovy 1.8.6では何もしませんが、アップグレードした後は機能するので、これは古いバグだと思います。それにもかかわらず、どちらのバージョンでもc内部にはアクセスできません。method()

だから私の質問は:

  1. @Field内部 で注釈が付けられた変数にアクセスできないのはなぜmethod()ですか?
  2. 内部のスクリプト変数を参照するにはどうすればよいmethod()ですか?
4

2 に答える 2

37

groovyスクリプトの宣言の外にメソッドまたはステートメントがある場合class、暗黙のクラスが作成されます。あなたの質問に答えるには:

  1. あなたの例では、両方とも暗黙のクラスのメンバーであるためfunc()、フィールドにアクセスできます。クラスはそうではないので、できませんcMain

  2. スクリプト変数への参照をに渡す必要がありますmethod()。1つの方法は、暗黙的に定義されたbindingオブジェクトを渡すことです。これを介して、すべてのスクリプトスコープ変数にアクセスできます。

例:

#!/usr/bin/groovy
import groovy.transform.Field;

//println org.codehaus.groovy.runtime.InvokerHelper.getVersion()

def a = 42;
b = "Tea"
@Field def c = "Cheese"

void func()
{
    // println a // MissingPropertyException
    println b // prints "Tea"
    println c // prints "Cheese" with groovy 2.1.2, MissingPropertyException with groovy 1.8.6

}

class Main
{
    def scriptObject
    def binding

    def method()
    {
        // println a // MissingPropertyException
        println binding.b
        println scriptObject.c
    }
}

func();
new Main(scriptObject: this, binding: binding).method();
于 2013-03-25T16:26:41.643 に答える
10

このスクリプトMainは、同じファイル内で2つの別個のクラスとして生成されます。

MainScriptクラスの内部クラスではないため、scriptクラス内のフィールドを表示できませんjava.lang.Object c

このスクリプトをstatic main( args )メソッド(および内部Mainクラス)を含むクラスで明示的にラップするか、スクリプトクラスのインスタンスを次のようなメソッドに渡す必要があります。Main.method( this )

これは、上記のスクリプトが生成する種類のものです。

class Script032034034 {
  Object c

  Script032034034() {
    c = 'Cheese'
  }

  Object run() {
    Object a = 42
    b = 'Tea'
    func()
    new Main().method()
  }

  void func() {
    println b
    println c
  }
}

class Main {
  Object method() {
  }
}
于 2013-03-25T16:28:30.617 に答える