❌ 本部分還沒有完成,但你能夠經過 Miles 的博客(下方有連接)得到更多瞭解 :-)函數
讓咱們開始來討論這個類型,此次要藉助下「集合論」,而後把咱們已經學過的 A with B
當作一個「交集類型」。spa
爲何呢?由於只有同時帶有類型 A
和類型 B
的對象才能符合這個類型,所以在集合論中,它將是一個交集。此外,咱們思考下什麼是「聯合類型」。scala
這是兩個集合的聯合,逐集看每一個元素的類型要麼是 A
或者 B
。咱們的任務是使用 Scala 類型系統來引入這樣的類型。雖然它們不是 Scala 中的第一等構造(不是內置的),咱們也能夠很容易地實現和使用它們。Miles Sabin 在博客中經過「 Curry-Howard 同構」深刻地解釋了這一技術,若是你比較好奇,能夠去看看。code
type |∨|[T, U] = { type λ[X] = ¬¬[X] <:< (T ∨ U) }
def size[T : (Int |∨| String)#λ](t : T) = t match {
case i : Int => i
case s : String => s.length
}複製代碼
自從咱們開始討論 Scala 中一些不常見的類型,咱們就會安排專門的章節來介紹每個類型。延遲初始化(Delayed Init)實際上只是一種編譯器的技巧而已,它對類型系統而言並非很是重要。可是一旦你理解了它,就會明白 scala.App
是如何運做的,因此看看下面的例子吧:對象
object Main extends App {
println("Hello world!")
}複製代碼
查看這段代碼,根據咱們已知的 Scala 基礎知識,會下這樣結論:「那麼,println
是在 Main
類的構造函數中!」。這一般是對的,但在這裏卻並非這樣的,由於 App
繼承了 DelayedInit
特質:繼承
trait App extends DelayedInit {
// code here ...
}複製代碼
讓咱們來看看延遲初始化的特質的完整源代碼:get
trait DelayedInit {
def delayedInit(x: => Unit): Unit
}複製代碼
正如你所見,它並無包含任何的實現 — 全部圍繞它的工做實際上都是編譯器執行的,它將以一種特殊的方式來對待「繼承了 DelayedInit
」的類和單例(注:特質不會像這樣同樣重寫)。編譯器
特殊待遇是這樣子的:博客
咱們立刻來舉個例子,手動來從新實現一遍 App
爲咱們自動作的事情(在 delayedInit
的幫助下):
// we write:
object Main extends DelayedInit {
println("hello!")
}
// the compiler emits:
object Main extends DelayedInit {
def delayedInit(x: => Unit = { println("Hello!") }) = // impl is left for us to fill in
}複製代碼
使用這種機制,你能夠隨時運行你的類的主體。咱們已經瞭解了延遲初始化如何工做,接下來再來實現下咱們本身版本的 scala.App
吧(這實際上也是以相同方式實現的)。
override def delayedInit(body: => Unit) {
initCode += (() => body)
}
def main(args: Array[String]) = {
println("Whoa, I'm a SimpleApp!")
for (proc <- initCode) proc()
println("So long and thanks for all the fish!")
}
}
// Running the bellow class would print print:
object Test extends SimpleApp { //
// Whoa, I'm a SimpleApp!
println(" Hello World!") // Hello World!
// So long and thanks for all the fish!
}複製代碼