Scala 为什么可以';类val参数不能按名称调用吗?

Scala 为什么可以';类val参数不能按名称调用吗?,scala,Scala,我正试图使用一个类作为一个接口聚合一组API函数的代理。其中有几个是空函数,但我不希望在类构造函数中包含它们来触发API调用。我现在的解决方案是将调用包装在一个文本空函数newmyclass(()=>apiCall)中,然后显式调用成员函数。这并不是那么糟糕,但我想知道是否有一个技术原因,我不能仅仅使用callbyname参数来传递对该方法的惰性引用 例如: scala> class MyClass(val apiCall: => String) <console>:1:

我正试图使用一个类作为一个接口聚合一组API函数的代理。其中有几个是空函数,但我不希望在类构造函数中包含它们来触发API调用。我现在的解决方案是将调用包装在一个文本空函数
newmyclass(()=>apiCall)
中,然后显式调用成员函数。这并不是那么糟糕,但我想知道是否有一个技术原因,我不能仅仅使用callbyname参数来传递对该方法的惰性引用

例如:

scala> class MyClass(val apiCall: => String)
<console>:1: error: `val' parameters may not be call-by-name
       class MyClass(val apiCall: => String)
scala>classmyclass(val-apiCall:=>String)
:1:错误:`val'参数不能按名称调用
类MyClass(val apiCall:=>字符串)

Edit我应该指定我的问题是为什么类不能有
val
参数。添加了一个示例。

一个类很可能有按名称调用的参数,只要它们不是
val
var

> scala
Welcome to Scala version 2.11.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_55).
Type in expressions to have them evaluated.
Type :help for more information.

scala> class Foo(f: => Unit) {
     |   def run(): Unit = f
     | }
defined class Foo

scala> new Foo(println("hello"))
res0: Foo = Foo@5da6b8c6

scala> res0.run()
hello
val
var
参数不能按名称显示的原因很简单,就是类字段不能按名称显示,只能按局部变量显示。因此,以下内容无效:

scala> class FooInvalid(val v: => Unit) {
<console>:1: error: `val' parameters may not be call-by-name
       class FooInvalid(val v: => Unit) {
                               ^
最后,不必将
v
定义为
()=>单元类型的
val
,您可以将其定义为
单元类型的
def
。然后你得到了一开始你可能想要的行为:

scala> class FooDef(v0: => Unit) {
     |   def v: Unit = v0
     | }
defined class FooDef

scala> new FooDef(println("hello"))
res5: FooDef = FooDef@2e04a041

scala> res5.v
hello

有人可能会争辩说编译器应该自己进行这种转换,但这与
val
必须是稳定的语义不一致(例如,使用稳定的值,您可以
导入x.。
其成员,您不能使用不稳定的值),因为
def
(即使没有
()
)是一个不稳定的值。最好将这个小的重写留给用户,而不是引入一个非常奇怪的错误。

但如果它们是
val
s,就不要这样,这是我的问题。对不起,应该更具体一点。回答得很好。关于与局部变量的比较,局部变量不能按名称命名,但可以是惰性的。编译器对此也抱怨不已,建议使用按名称参数,这是因为惰性参数通常不存在。在某个时候,它们被考虑包含在Scala中,但结果证明它们的实现比合理的要困难得多,所以被放弃了。
scala> class FooDef(v0: => Unit) {
     |   def v: Unit = v0
     | }
defined class FooDef

scala> new FooDef(println("hello"))
res5: FooDef = FooDef@2e04a041

scala> res5.v
hello