主要來自 Scala 語言發明人 Martin Odersky 教授的 Coursera 課程 《Functional Programming Principles in Scala》。java
這一集字幕不一樣步-,-
,聽得有點費力!python
類的概念和其餘語言裏面很類似,基類,子類,父類啥的叫法差很少。在 Scala 中,全部用戶自定義的類都是另一個類的子類,若是沒有顯式給定父類,java 裏面默認繼承 java.lang,scala 裏面是 Object。不管基類中的方法有沒有具體實現,子類均可以用 override
從新定義,回想起以前強大的 toString
了嗎?編程
舉一個二叉樹的例子:api
package week3 object insets { val t1 = new NonEmpty(3, Empty, Empty) //> t1 : week3.NonEmpty = {.3.} val t2 = t1 incl 4 //> t2 : week3.IntSet = {.3{.4.}} val t3 = new NonEmpty(5, Empty, Empty) //> t3 : week3.NonEmpty = {.5.} t2 union t3 //> res0: week3.IntSet = {{{.3.}4.}5.} } abstract class IntSet { // 抽象類做爲基類,沒法實例化,定義了三個接口 def contains(x: Int): Boolean // 查找是否包含 x def incl(x: Int): IntSet // 若是 x 不存在,將 x 放入二叉樹中 def union(x: IntSet): IntSet // 兩棵樹融合 } object Empty extends IntSet { // Empty 是 IntSet 的 subclass,`object` 表示單例模式,全部空節點均可以用一個對象來表示 def contains(x: Int): Boolean = false def incl(x: Int): IntSet = new NonEmpty(x, Empty, Empty) def union(other: IntSet): IntSet = other override def toString = "." // 空節點打印"." } class NonEmpty(elem: Int, left: IntSet, right: IntSet) extends IntSet { def contains(x: Int): Boolean = if (x < elem) left contains x else if (x > elem) right contains x else true def incl(x: Int): IntSet = // 實際上建立了一個新樹,新樹和舊樹共用未改變的子樹 // 這個叫 persistent data structure,是把函數式編程擴展到 collections 的關鍵之一 // 反正他是這麼說的 `-,-` if (x < elem) new NonEmpty(elem, left incl x, right) // 一重一重地複製節點 else if (x > elem) new NonEmpty(elem, left, right incl x) else this def union(other: IntSet): IntSet = ((left union right) union other) incl elem // override def toString = "{" + left + elem + right + "}" //強大的遞歸啊 }
沒學過 java,估計和 java 中 package 管理同樣。ssh
在源碼最頂端寫上 package week3
表示這個文件的 object 或者 class 屬於這個包。要使用某一個類,能夠在源碼中用全名 week3.classA
,也能夠像 python 同樣在最開始 import,源碼中間用類名:ide
除了從包導入,還能夠從 object 導入。全部 Scala 程序默認導入一些 entities,好比 scala 中的 Int,java.lang 中的 Object,scala.Predef 中的斷言等。更多信息能夠查看 scala 的標準庫。函數式編程
在 java 和 scala 中,一個類只能有一個父類(單繼承),如何實現多繼承,scala 中採用 traits。trait 像 java 裏面的接口,偏抽象,可是更強大,能夠包含 field 和具體方法,可是不能有value參數。子類可只能繼承一個父類,可是能夠繼承任意多個 traits,例如:class Square extends Shape with Planar with Moveble
。函數
scala 類型結構以下,實線表示繼承,虛線表示隱式轉化。學習
Any
是全部類型的基本類,包含的方法有:‘==’,‘!=’,‘equals’,‘hashCode’,‘toString’AnyVal
是數值類型的基本類。AnyRef
是全部引用類型的基本類,也是 java.lang.Object 的別名。Nothing
是全部類的子類型。主要做用是異常類與collection中的一個空元素。Null
是全部類的子類型。可是與 AnyVal 的子類型不兼容。
Q:if (true) 1 else False
的返回類型是什麼?
A:int 和 boolean 類型,返回父類 AnyVal。測試
Polymorphism 意味着函數能夠以多種類型出現。一張 PPT 總結 Polymorphism:
假設咱們要創建一個 list 類,它可能包含了不一樣的數據類型(整數,布爾,list自身類型等),例子以下:
這時須要用泛型來表示。新建一個package叫week4,在其中新建一個 trait。它的兩個‘子類’分別爲 Cons 和 Nil,分別表示含有元素的節點和空節點。
package week4 // [T] 是類型參數,好比int,double之類。是泛型編程的基礎 trait List[T] { def isEmpty: Boolean def head: T def tail: List[T] } class Cons[T](val head: T, val tail: List[T]) extends List[T] { def isEmpty = false // head 和 tail 已經在初始化中實現 } class Nil[T] extends List[T] { def isEmpty = true def head: Nothing = throw new NoSuchElementException("Nil.head") // Nothing 是任何類型的子類,因此也是 T 的子類 def tail: Nothing = throw new NoSuchElementException("Nil.tail") }
在 week4 中新建一個 scala worksheet,測試一下上述代碼:
package week4 import week4._ object nth { // 建立一個含有一個元素的 list def singleton[T](elem: T) = new Cons(elem, new Nil) //> singleton: [T](elem: T)week4.Cons[T] singleton[Int](3) //> res0: week4.Cons[Int] = week4.Cons@71be98f5 singleton(3) // 編譯器能夠從 3 推到出 T 是 Int // 尋找 list 中的第 n 個元素 def nth[T](n: Int, xs: List[T]): T = if (xs.isEmpty) throw new IndexOutOfBoundsException else if (n == 0) xs.head else nth(n - 1, xs.tail) //> nth: [T](n: Int, xs: week4.List[T])T // 建立一個 list = [1, 2, 3] val list = new Cons(1, new Cons(2, new Cons(3, new Nil))) nth(2, list) //> res2: Int = 3 }
這裏是課程前四次的大概內容,由於第一次課是教你怎麼安裝,因此實際內容只有三次課,後面還有四次課。整體來講,函數式編程給人不少啓發,可是若是不是真正須要用,也不宜佔用太多時間去學習。暑假要去實習了,等下學期再學吧。