2011-03-09 85 views
5

我正在尋找Scala中所有鉤子的簡明文檔。鉤子是可以攔截常見行爲的程序流中的任何情況。這些情況包括:Scala中的鉤子模式

  • 類的聲明或性狀
  • 訪問方法和字段螺紋
  • 混入物,繼承

我從一個Ruby的背景的,其中對於例如,method_missing允許攔截不存在的方法調用。

在Scala中可以使用這樣的鉤子嗎?

Matthias

+0

在相關說明,另請參閱http://stackoverflow.com/questions/3105594/is-there-a-method-missing-in-scala – VonC 2011-03-09 07:16:56

回答

7

在Scala 2.8或更早的版本中,沒有相當於method_missing。在Scala 2.9(開發中)中,將添加一個Dynamic特徵。對聲明動態特徵的對象的未知方法調用將被編譯器自動轉換爲invokeDynamic。這個想法是以安全和理智的方式獲得動態類型語言的一些力量,而不需要支付動態類型的性能開銷,如果不需要的話。它還簡化了從Scala內部調用動態語言中定義的對象時的互操作性問題。除此之外,在Scala中掛鉤新行爲主要通過經典繼承完成,或通過隱式轉換爲對象添加新功能。

3

不,他們不是。在靜態語言中,面向方面的編程可以用於某些相同的目的。請參見Can I do Aspect Oriented Programming in Scala? 但當然,「類或特徵的聲明」和「混入線程,繼承」是而不是控制流的一部分。如果你想攔截它們,你需要一個編譯器插件。

3

Scala傾向於鼓勵使用閉包,而不是您正在討論的鉤子類型(其中大多數由於靜態類型和編譯而無法方便實現)。

這要求您事先知道哪些地方可能需要靈活性,但在可用時非常強大且易於使用。例如,假設您有打印出人的名字的方法:

case class Name(first: String, last: String) { 
    def title = last + ", " + first(0).toUpper + "." 
} 
trait Familiar extends Name { 
    override def title = first + " " + last(0).toUpper + "." 
} 

def listing(names: Array[Name]) = names.foreach(name => println(name.title)) 

val jd1 = new Name("John","Doe) 
listing(Array(jd1)) // Prints Doe, J. 
val jd2 = new Name("John","Doe") with Familiar 
listing(Array(jd2)) // Prints John D. 

,但如果你真的將要改變名稱印刷了很多,你最好的建築在:

case class Name(first: String, last: String) { 
    def title = last + ", " + first(0).toUpper + "." 
} 

def listing(names: Array[Name], address: Name => String = _.title) = 
    names.map(address).foreach(println) 

val jd = new Name("John", "Doe") 
listing(Array(jd)) // Uses default, so prints Doe, J. 
listing(Array(jd), n => n.first + " " + n.last(0).toUpper + ".") // Prints John D. 
1

Scala中沒有這樣的東西。或者,更準確地說,靜態類型確保我們知道編譯代碼時會發生什麼。任何這樣的鉤子都會在運行時改變行爲,這將破壞靜態類型的目的。

可以通過編譯器插件修改編譯時間的行爲,甚至可以通過類加載器在類加載時更改內容。