jira.codehaus.org

  • Log In Access more options
    • Online Help
    • Keyboard Shortcuts
    • About JIRA
    • JIRA Credits
    • What?s New
  • Dashboards Access more options (Alt+d)
  • Projects Access more options (Alt+p)
  • Issues Access more options (Alt+i)
  • groovy
  • GROOVY-2503 MOP 2.0 design inflluencing issues
  • GROOVY-2641

Dynamically created closure handles delegate differently from statically created closure

  • Log In
  • Views
    • XML
    • Word
    • Printable

Details

  • Type: Sub-task Sub-task
  • Status: Open Open
  • Priority: Major Major
  • Resolution: Unresolved
  • Affects Version/s: 1.5.4
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None
  • Environment:
    CentOS 5 n Intel with java 1.6.0_03-b05
  • Testcase included:
    yes

Description

The following script executes two closures. One is statically defined in class Test,
the other is returned by Test.makeClosure(). In each case the delegate of the
Closure is set to be an instance of class Delegate, but in one case a call to
method "foo()" appears to resolve to Test.foo(), while in the second it appears
to resolve to Delegate.foo().

I showed this to Dierk at the G2 conference in Reston, and he asked me to post
it as a bug.
=====================================================================

class Test {

def foo() { "NOT the delegate" }

def makeClosure() {
def closure = { println foo() println delegate.foo() }
}

static staticClosure = { println foo() println delegate.foo() }

}

class Delegate {
def foo() { "delegate" }
}

Closure dynamicClosure = new Test().makeClosure()
dynamicClosure.setDelegate(new Delegate())
dynamicClosure.call()

Test.staticClosure.setDelegate(new Delegate())
Test.staticClosure.call()
==================================================================

Expected Output:

delegate
delegate
delegate
delegate

Actual Output:

NOT the delegate
delegate
delegate
delegate

Activity

  • All
  • Comments
  • Work Log
  • History
  • Activity
Hide
Permalink
Roshan Dawrani added a comment - 09/Jan/09 11:09 AM - edited

I think this is not an issue and the actual behavior is correct.

This is because the invocation is first tried on owner and then on the delegate. When foo() is invoked by dynamicClosure (returned by Test.makeClosure()), it finds it on the owner (Test.foo()) and invokes it. Since staticClosure is static member of Test, it does not have access to non-static foo() of Test and since it does not find foo() on owner, it next tries the delegate and finds it there and invokes it.

To see the same behavior in both dynamicClosure and staticClosure, if Test.foo() is made static as in:

class Test {
    static def foo() { "NOT the delegate" }
    def makeClosure() {
        def closure = { 
                println foo() 
                println delegate.foo() 
        }
    }
    static staticClosure = { 
        println foo() 
        println delegate.foo() 
    }
}

class Delegate {
def foo() { "delegate" }
}

Closure dynamicClosure = new Test().makeClosure()
dynamicClosure.setDelegate(new Delegate())
dynamicClosure.call() 

Test.staticClosure.setDelegate(new Delegate())
Test.staticClosure.call()

Now, the output is:
NOT the delegate // dynamicClosure's foo() goes to owner now since it has access to static Test.foo()
delegate
NOT the delegate // staticClosure's foo() also goes to owner now since it has access to static Test.foo()
delegate

Show
Roshan Dawrani added a comment - 09/Jan/09 11:09 AM - edited I think this is not an issue and the actual behavior is correct. This is because the invocation is first tried on owner and then on the delegate. When foo() is invoked by dynamicClosure (returned by Test.makeClosure()), it finds it on the owner (Test.foo()) and invokes it. Since staticClosure is static member of Test, it does not have access to non-static foo() of Test and since it does not find foo() on owner, it next tries the delegate and finds it there and invokes it. To see the same behavior in both dynamicClosure and staticClosure, if Test.foo() is made static as in:
class Test {
    static def foo() { "NOT the delegate" }
    def makeClosure() {
        def closure = { 
                println foo() 
                println delegate.foo() 
        }
    }
    static staticClosure = { 
        println foo() 
        println delegate.foo() 
    }
}

class Delegate {
def foo() { "delegate" }
}

Closure dynamicClosure = new Test().makeClosure()
dynamicClosure.setDelegate(new Delegate())
dynamicClosure.call() 

Test.staticClosure.setDelegate(new Delegate())
Test.staticClosure.call()
Now, the output is: NOT the delegate // dynamicClosure's foo() goes to owner now since it has access to static Test.foo() delegate NOT the delegate // staticClosure's foo() also goes to owner now since it has access to static Test.foo() delegate

People

  • Assignee:
    Unassigned
    Reporter:
    Bruce Cota
Vote (0)
Watch (0)

Dates

  • Created:
    27/Feb/08 8:14 AM
    Updated:
    30/Dec/10 8:39 AM
  • Atlassian JIRA (v5.0.4#731-sha1:3aa7374)
  • Report a problem
  • Powered by a free Atlassian JIRA open source license for Codehaus. Try JIRA - bug tracking software for your team.