有没有办法让构造函数的by-name-parameters工作?我需要一种方法来提供一个代码块,它在对象内部按需/延迟/按名称执行,这个代码块必须能够访问类方法,就像代码块是类的一部分一样
以下测试用例失败:
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
}
}
}
输出:
foo
method
pre-code
post-code
--------
pre-code
foo
post-code
答案 0 :(得分:5)
这是因为当您制作这样的实例时:
val tst = new ByNameCons {
...
}
..你实际上正在创建一个匿名类,就像在java中一样。 上面的代码与:
相同val tst = new ByNameCons() { ... }
..而传递by-name的正确语法是:
val tst = new ByNameCons( { ... } )
对于构造函数和函数,您不能以相同的方式省略括号。
答案 1 :(得分:3)
val tst = new ByNameCons( {
println("foo")
} )
认为这样做可能更容易:
object ByNameCons {
def apply(code: => Unit) = new ByNameCons(code)
}
val tst = ByNameCons { // no "new" here -- can't mix traits either
println("foo")
}
答案 2 :(得分:1)
我不知道为什么,但似乎在创建类时使用{}或()更改了行为。使用以下课程
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
现在改为以另一种方式定义,
scala> val parens = new Coder(println("testing"))
parens: Coder = Coder@dca3ed
scala> parens exec
before
testing
after
根据需要。似乎在第一种表示法中,编译器将括号解释为要评估为Unit
的块,而不是匿名函数,在调用时,它将计算为Unit
。
FWIW,使用({...})也可以。