web-dev-qa-db-ja.com

defを使用して変数を定義する場合と使用しない場合の変数の定義の違いは何ですか?

Jenkins DSLに関連して、次の違いは何ですか。

def cwd = pwd()

そして

cwd = pwd()

12
Itai Ganot

それは範囲の違いです。 Groovyスクリプトでは、「def」やその他のタイプを使用せずに変数に値を割り当てると、スクリプトのグローバル変数である「バインディング」に値が追加されます。つまり、スクリプト内のすべての関数からアクセスできます。これは、スクリプトの先頭に変数を定義した場合とよく似ています。

複数のスレッドがスクリプトに作用していると、予期しない動作が発生する可能性があります。

def a = {
  x = 1
  println x
}
def b = {
  x = 2
  println x
}
new Thread(a).start()
new Thread(b).start()

... 2つのもの、2つの2つ、またはそれらの組み合わせを生成できます。

対照的に、「def」を使用すると、ローカル変数が作成されます。

def a = {
  def x = 1
  println x
}
def b = {
  def x = 2
  println x
}
new Thread(a).start()
new Thread(b).start()

...常に1と2を任意の順序で出力します。

10
Corrodias

これは良い質問ですが、Groovyの質問です。

私の理解では、defキーワードなしで変数を定義することはスクリプトからは機能しますが、クラスメソッドを使用している場合は機能しません。この例 ブログ投稿

class MyTest {
    def testMethod() {
        y = 3
        println y
    }    
}

t = new MyTest()
t.testMethod()

変数tは問題なく定義されますが、y定義は例外をスローします。

つまり、私たちのコンテキスト(Jenkinsパイプライン)では、常にスクリプトコンテキストにあり、変数がスクリプトにバインドされるため、defキーワードなしで変数を定義できます。ただし、defキーワードを使用することをお勧めします。これは、変数をインスタンス化するタイミングがわかるため、変数定義の重複の問題を回避できるためです(defキーワード同じ変数を2回定義した場合、少なくともコンパイルは失敗します)。

最後に、 Groovyドキュメント から:

Groovyでdefを使用する場合、実際の型ホルダーはObjectです(したがって、defで定義された変数に任意のオブジェクトを割り当て、メソッドがdefを返すように宣言されている場合は任意の種類のオブジェクトを返すことができます)。

したがって、具体的に定義する変数のタイプを指定することをお勧めします。あなたの場合、cwdを次のように定義できます:

String cwd = pwd()

それはあなたが次のようなことをすることを禁じます:

def cwd = pwd()
cwd = 1000     // Valid code

String cwd2 = pwd()
cwd2 = 1000    // Will fail compilation
1
Pom12