2013-08-04 22 views
3

斯卡拉式引導建議始終明確地定義返回類型期望使用Unit時:什麼時候應該Scala方法def使用顯式定義的返回類型?

方法應該按照以下方式進行聲明:

def foo(bar: Baz): Bin = expr 

,唯一的例外是方法哪個返回Unit。這種 方法應該使用Scala的語法糖,以避免意外 混亂的返回類型:

def foo(bar: Baz) { // return type is Unit 
    expr 
} 
+2

Ma rtin Odersky建議避免過程語法。參見[Keynote-Scala with Style chapter 45](http://www.parleys.com/play/51c1994ae4b0d38b54f4621b/chapter45/about)。 [另請參閱討論在[這個答案]評論(http://stackoverflow.com/a/17502581/406435))。 – senia

+1

@senia ok,如果過程語法不好,那麼最好是:顯式聲明'Unit'是返回類型還是省略它(編譯器會自己推斷類型)? – MyTitle

+0

就像任何其他類型。在一些指南中,建議在公共方法中明確指定類型。我想這是一個主要基於觀點的問題。 – senia

回答

1

正如論者指出,馬丁·奧德斯基在鏈接的主題討論這一點。當然,正如「何時......」所表明的那樣,這最終是一個文體問題,所以人們只能提出意見。

兩件事:(1)類型是/否,和(2)過程語法是/否。


(1)很明顯,對於純API(沒有實現),您必須指定返回類型。我會將此擴展到任何方法實現,它同時也是API。也就是說,如果你的方法沒有實現一個特徵,在這種情況下,當你的返回類型不同時,編譯器會給你一個錯誤,你應該註釋該方法。 私有和本地方法可以推斷返回類型,除非您很難第一眼看出類型,或者您被迫(例如,在遞歸方法調用中)。也有人說,當你給出明確的返回類型時,彙編是更快

如果你有一個簡短的方法與「easy」返回類型,我認爲推斷很好。防爆。

trait Foo { 
    def sqrt(d: Double) = math.sqrt(d) 

    def toString = "Foo" 

    def bar = new Bar(123) 
} 

(但已經有人可能會說,它可能不是很明顯,math.sqrt返回Double)。

儘管更詳細的,你讓代碼更易讀,你避免(一)泄露有關實現或子類信息,其中超型sufficies:

trait Before { 
    def bar = new BarImpl 

    def seq = Vector(1, 2, 3) 
} 

trait After { 
    def bar: Bar = new BarImpl 

    def seq: IndexedSeq[Int] = Vector(1, 2, 3) 
} 

和(b)你避免意外返回東西你不打算從結構類型錯誤的集合類型等


(2)直到最近我首選過程語法,但經過重新討論後,許多人對此表示不滿,我嘗試使用明確的: Unit =註釋,現在我更喜歡它了。我認爲程序語法清楚地表明,一種方法有副作用,但確實也很清楚地表明瞭這一點。此外,它常常能去除大括號的量:

trait Before { 
    private var _x = 0 
    def x: Int = _x 
    def x_=(value: Int) { _x = value } 
} 

trait After { 
    private var _x = 0 
    def x: Int = _x 
    def x_=(value: Int): Unit = _x = value // if double = confuses you, use new line? 
} 

我發現許多情況下,身體開始與if,圖案match,​​塊或future生成,收集map表達式等,在這些情況下去掉大括號是很好的:

trait Before { 
    def connect()(implicit tx: Tx) { 
    values.foreach { case (x, _) => 
     x.changed += this 
    } 
    } 
} 

trait After { 
    def connect()(implicit tx: Tx): Unit = 
    values.foreach { case (x, _) => 
     x.changed += this 
    } 
} 
相關問題