2014-07-09 46 views
4

我想使用一個類來聚合作爲一個單一的接口API函數的一堆代理。其中有一些是無功函數,但我不希望將它們包含在類構造函數中以觸發API調用。我現在的解決方案是將該呼叫包裝在一個字面無限制函數new myClass(() => apiCall)中,然後明確地調用成員函數。這並不是那麼糟糕,但我想知道是否有技術原因,我不能只使用名​​稱參數來傳遞對方法的惰性引用?爲什麼val類參數不能按名稱調用?

例子:

scala> class MyClass(val apiCall: => String) 
<console>:1: error: `val' parameters may not be call-by-name 
     class MyClass(val apiCall: => String) 

編輯我應該指定,我的問題是,爲什麼一個類不能有val參數。增加了一個例子。

回答

5

一個類可以很好得的call-by-名稱參數,只要他們不valvar

> 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 = [email protected] 

scala> res0.run() 
hello 

一個valvar參數不能用名字的原因很簡單,一個class字段不能是名稱,不能超過局部變量。所以下面是無效的:

scala> class FooInvalid(val v: => Unit) { 
<console>:1: error: `val' parameters may not be call-by-name 
     class FooInvalid(val v: => Unit) { 
          ^

但是,可能有被分配了一個用名字參數,作爲功能val場,像這樣(但你必須使用()爲調用點):

scala> class FooVal(v0: => Unit) { 
    | val v:() => Unit =() => v0 
    | } 
defined class FooVal 

scala> new FooVal(println("hello")) 
res2: FooVal = [email protected] 

scala> res2.v 
res3:() => Unit = <function0> 

scala> res2.v() 
hello 

最後,而不是定義v() => Unitval,你可以把它定義爲Unitdef。然後你讓你在第一時間大概想要的行爲:

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

scala> new FooDef(println("hello")) 
res5: FooDef = [email protected] 

scala> res5.v 
hello 

有人可能會說編譯器應該做的這種轉變本身,但不會與語義一個val必須一致穩定 (例如,一個穩定的值,您可以import x._其成員,你不能做一個不穩定的值),因爲def(即使沒有())是一個不穩定的值。最好把這個小改寫留給用戶,而不是引入一個非常奇怪的缺點。

+0

但是,如果他們是'val',那就是我的問題。對不起,應該是更具體。 – acjay

+0

好的。考慮到這一點,我已經更新了我的答案。 – sjrd

+0

很好的答案。關於你與局部變量的比較,局部變量不能是名稱,但可能是懶惰的。儘管如此,編譯器還是抱怨這一點,建議使用名字參數,不要少。 – acjay

相關問題