Name Parameters for By-Name Constructors
Coming from my other question , is there a way to get by-name parameters for working constructors? I need a way to provide a codeblock that is requested / lazy / by-name within an object, and that codeblock should be able to access the method classes as if the codeblock was part of a class.
Testcase fails:
package test
class ByNameCons(code: => Unit) {
def exec() = {
println("pre-code")
code
println("post-code")
}
def meth() = println("method")
def exec2(code2: => Unit) = {
println("pre-code")
code2
println("post-code")
}
}
object ByNameCons {
def main(args: Array[String]): Unit = {
val tst = new ByNameCons {
println("foo")
meth() // knows meth() as code is part of ByNameCons
}
tst.exec() // ByName fails (executed right as constructor)
println("--------")
tst.exec2 { // ByName works
println("foo")
//meth() // does not know meth() as code is NOT part of ByNameCons
}
}
}
Output:
foo
method
pre-code
post-code
--------
pre-code
foo
post-code
a source to share
This is because when you make an instance like this:
val tst = new ByNameCons {
...
}
.. you are actually creating an anonymous class like in java. The above code is the same as:
val tst = new ByNameCons() { ... }
.., whereas the correct syntax for passing by name is:
val tst = new ByNameCons( { ... } )
You cannot omit parentheses in the same way for constructors as you can for functions.
a source to share
I don't know why, but it seems that when using the class {} or (), the behavior changes when the class is created. Using the following class,
class Coder(code: => Unit) {
def exec = {
println("before")
code
println("after")}
}
}
scala> val brackets = new Coder {println("testing")}
testing
brackets: Coder = $anon$1@1af7a03
scala> brackets exec
before
after
Now if defined otherwise,
scala> val parens = new Coder(println("testing"))
parens: Coder = Coder@dca3ed
scala> parens exec
before
testing
after
optional. It seems that in the first notation, the compiler interprets the parentheses as a block to be evaluated as Unit
, instead of an anonymous function, which, when called, evaluates as Unit
.
FWIW using ({...}) also works great.
a source to share