Groovy :“def x = 0”에서“def”의 목적은 무엇입니까?


180

다음 코드에서 ( Groovy Semantics Manual 페이지 에서 가져온 ) 왜 키워드 앞에 할당을 붙 def입니까?

def x = 0
def y = 5

while ( y-- > 0 ) {
    println "" + x + " " + y
    x++
}

assert x == 5

def키워드는 제거 할 수 있으며,이 조각은 동일한 결과를 생성 할 것입니다. 키워드 의 효과 는 무엇 def입니까?

답변:


278

기본 스크립트의 구문 설탕입니다. "def"키워드를 생략하면 변수가 현재 스크립트의 바인딩에 들어가고 groovy는이 변수를 전역 범위 변수처럼 취급합니다.

x = 1
assert x == 1
assert this.binding.getVariable("x") == 1

대신 def 키워드를 사용하면 변수가 스크립트 바인딩에 포함되지 않습니다.

def y = 2

assert y == 2

try {
    this.binding.getVariable("y") 
} catch (groovy.lang.MissingPropertyException e) {
    println "error caught"
} 

인쇄 : "오류가 발생했습니다"

큰 프로그램에서 def 키워드를 사용하면 변수를 찾을 수있는 범위를 정의하고 캡슐화를 유지하는 데 도움이되므로 중요합니다.

스크립트에서 메소드를 정의하면 범위 내에 있지 않으므로 기본 스크립트 본문에서 "def"로 작성된 변수에 액세스 할 수 없습니다.

 x = 1
 def y = 2


public bar() {
    assert x == 1

    try {
        assert y == 2
    } catch (groovy.lang.MissingPropertyException e) {
        println "error caught"
    }
}

bar()

"오류가 발견되었습니다"

"y"변수는 함수 내에서 범위 내에 있지 않습니다. groovy가 변수에 대한 현재 스크립트의 바인딩을 검사하므로 "x"는 범위 내에 있습니다. 앞서 말했듯이, 이것은 빠르고 더러운 스크립트를 더 빨리 입력 할 수 있도록하는 구문 설탕입니다 (종종 하나의 라이너).

더 큰 스크립트에서 좋은 습관은 항상 "def"키워드를 사용하여 이상한 범위 지정 문제가 발생하거나 의도하지 않은 변수를 방해하지 않는 것입니다.


36

Ted의 답변 은 대본에 탁월합니다. Ben의 대답 은 수업의 표준입니다.

Ben이 말했듯이 "Object"로 생각하십시오. 그러나 Object 메소드에 제한을 두지 않기 때문에 훨씬 더 시원합니다. 이것은 수입과 관련하여 깔끔한 영향을 미칩니다.

예를 들어이 스 니펫에서 FileChannel을 가져와야합니다.

// Groovy imports java.io.* and java.util.* automatically
// but not java.nio.*

import java.nio.channels.*

class Foo {
    public void bar() {
        FileChannel channel = new FileInputStream('Test.groovy').getChannel()
        println channel.toString()
    }
}

new Foo().bar()

예를 들어 여기에 모든 것이 클래스 패스에있는 한 '날개'할 수 있습니다.

// Groovy imports java.io.* and java.util.* automatically
// but not java.nio.*
class Foo {
    public void bar() {
        def channel = new FileInputStream('Test.groovy').getChannel()
        println channel.toString()
    }
}

new Foo().bar()

1
new FileInputStream('Test.groovy').getChannel()수입품을 꺼낸 이유는 무엇입니까?
Alexander Suraphel

3
@AlexanderSuraphel "모든 것이 클래스 패스에있는 한"
Hanno

30

이에 따라 페이지 , def유형 이름에 대한 대체 단순히 별명으로 간주 할 수 있습니다 Object(즉 명시를 당신이 유형에 대해 신경 쓰지 않는다).


12

이 단일 스크립트에 관한 한 실질적인 차이는 없습니다.

그러나 키워드 "def"를 사용하여 정의 된 변수는 로컬 변수, 즉이 하나의 스크립트에 대해 로컬 변수로 취급됩니다. 앞에 "def"가없는 변수는 처음 사용할 때 소위 바인딩에 저장됩니다. 바인딩은 스크립트 사이에 사용 가능해야하는 변수 및 클로저의 일반 저장 영역으로 생각할 수 있습니다.

따라서 두 개의 스크립트가 있고 동일한 GroovyShell로 스크립트를 실행하면 두 번째 스크립트는 "def"없이 첫 번째 스크립트에서 설정된 모든 변수를 얻을 수 있습니다.


8

"def"의 이유는 여기에 변수를 만들려고 groovy에게 알리기위한 것입니다. 우연히 변수를 만들지 않기 때문에 중요합니다.

스크립트 (Groovy 스크립트 및 groovysh를 사용하면 그렇게 할 수 있음)에서 다소 수용 가능하지만 프로덕션 코드에서는 발생할 수있는 가장 큰 악 중 하나이므로 모든 실제 그루비 코드에서 def로 변수를 정의 해야하는 이유는 무엇입니까? 수업).

다음은 왜 나쁜지에 대한 예입니다. 다음 코드를 복사하여 groovysh에 붙여 넣으면 (어설 션 실패없이) 실행됩니다.

bill = 7
bi1l = bill + 3
assert bill == 7

이런 종류의 문제는 찾아서 고치는 데 많은 시간이 걸릴 수 있습니다. 인생에서 한 번만 물렸더라도 경력 전체에서 변수를 수천 번 명시 적으로 선언하는 것보다 시간이 더 많이 걸립니다. 또한 그것이 선언되는 바로 눈에 분명해 지므로 추측 할 필요가 없습니다.

중요하지 않은 스크립트 / 콘솔 입력 (예 : 그루비 콘솔)에서는 스크립트 범위가 제한되어 있기 때문에 다소 수용 가능합니다. 나는 groovy가 스크립트에서 이것을 할 수있는 유일한 이유는 Ruby와 같은 방식으로 DSL을 지원하는 것이라고 생각합니다.


5

사실, 나는 그것이 똑같이 행동 할 것이라고 생각 하지 않습니다 ...

오른쪽에는 일반적으로 Groovy가 변수를 입력하기에 충분한 정보가 포함되어 있기 때문에 Groovy의 변수에는 여전히 TYPED 선언이 아닌 선언이 필요합니다.

def 또는 형식으로 선언하지 않은 변수를 사용하려고하면 코드가 포함 된 클래스의 멤버를 사용한다고 가정하므로 "No such property"라는 오류가 발생합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.