This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Odd behavior invoking thru anonymous class expression

2 replies
Jonathan Ross
Joined: 2008-12-31,
User offline. Last seen 42 years 45 weeks ago.
I was writing up a Java-to-Scala example and thought it would be interesting to use an anonymous class expression to support the "fluent interface" pattern, a la
object.someMethod().someOtherMethod()
In Java this is normally done by returning this or a helper class instance from each method. My use case was simpler, I only wanted to chain one method off another, so I wrote this (stripped down from the original code, with debugging added.)
class Gen
{
    def add(name: String) = {
        println("Adding " + name)
        new {
            def bind(pattern: String) = { 
                println("Binding " + pattern + " to " + name)
                this
            }
        }
    }
}
This gives the anonymous instance access to the original add() method scope, which is what I want. When I call it with
val gen = new Gen()
gen.add("a")
gen.add("b").bind("1")
My expectation is that I would get
Adding a
Adding b
Binding 1 to b
Instead the output is
Adding a
Adding b
Adding b
Binding 1 to b
Somehow, gen.add("b") is being called twice. Disassembling the generated class for the unit test shows this is indeed the case. If I instead use an intermediate val to hold the result of the add method, the behavior is correct:
val c = gen.add("c")
c.bind("2")
yields
Adding c
Binding 2 to c

This is with 2.7.3 RC1 (whatever arrives with the current plugin.)

Have the mysteries of Scala confounded me again or is this genuinely wrong?

Thanks,
Jonathan
View this message in context: Odd behavior invoking thru anonymous class expression
Sent from the Scala - User mailing list archive at Nabble.com.
James Iry
Joined: 2008-08-19,
User offline. Last seen 1 year 23 weeks ago.
Re: Odd behavior invoking thru anonymous class expression
Looks like a bug to me.  Please file it.

On Tue, Dec 30, 2008 at 7:21 PM, Jonathan Ross <jonross [at] alum [dot] mit [dot] edu> wrote:
Somehow, gen.add("b") is being called twice. Disassembling the generated class for the unit test shows this is indeed the case. If I instead use an intermediate val to hold the result of the add method, the behavior is correct:

odersky
Joined: 2008-07-29,
User offline. Last seen 45 weeks 6 days ago.
Re: Odd behavior invoking thru anonymous class expression

On Wed, Dec 31, 2008 at 5:01 AM, James Iry wrote:
> Looks like a bug to me. Please file it.
>
Yes, this looks like a bug. It seems to be linked to the fact that you
don't declare a superclass that contains the bind method. If you add
such a superclass, it works as expected:

abstract class Bind {
def bind(pattern: String): this.type
}

class Gen
{
def add(name: String) = {
println("Adding " + name)
new Bind {
def bind(pattern: String) = {
println("Binding " + pattern + " to " + name)
this
}
}
}
}

Adding a
Adding b
Binding l to b

Cheers

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland