1. 程式人生 > >scala中的多型 Ad-hoc polymorphism和type class

scala中的多型 Ad-hoc polymorphism和type class

多型的型別(polymorphism)
(1) parametric多型
下面例子來自scalaz教程:
scala> def head[A](xs: List[A]): A = xs(0)
head: [A](xs: List[A])A

scala> head(1 :: 2 :: Nil)
res0: Int = 1

scala> case class Car(make: String)
defined class Car

scala> head(Car("Civic") :: Car("CR-V") :: Nil)
res1: Car = Car(Civic)

可以看出引數多型與型別無關。

2 sub-type 多型

OOP中子類重寫父類方法,父類引用指向子類。

3 ad-hoc 多型
Ad-hoc polymorphism 的ad-hoc的意思是非通用的,臨時的,與引數多型相反:引數多型與型別無關,是通用的
,而ad-hoc多型與型別繫結,非通用。同時在Wikipedia中提到:
sub-type多型和ad-hoc多型都可以定義為一個介面,多個實現。區別在於,前者sub-type多型是在run-time環節決定選擇哪一個實現
(late binding 遲繫結),
而後者ad-hoc多型是在compile-time。第一種引數多型與型別無關,只有一種實現。

關於 ad-hoc 多型
The term ad hoc in this context is not intended to be pejorative。 ad-hoc 非通用不是貶義詞,相反, ad-hoc多型能讓scala這種靜態語言擁有動態語言的鴨子型別。(靜態語言golang通過interface,在編譯時推斷變數的型別也可以實現) ad-hoc多型在scala中可以通過隱式轉換和type class實現。 scala中type class由3部分組成: 1 type class (在scala中一般用trait) 2 class的例項 3 提供使用者呼叫的interface 下面程式碼中,type class是trait Assert部分,class例項放在object中,包括IntEqual和StrEqual, 提供使用者呼叫的interface,則是指通過implicit引數接收class例項的函式。 為了方便理解,下面程式碼實現了很簡單的功能:判斷兩個值是否相等。
/** * Created by me on 2018/9/10. */ trait Assert[M]{ def doAssert: (M, M) => Boolean } object Assert{ implicit val IntEqual =new Assert[Int] { def doAssert: (Int, Int) => Boolean = (value: Int, expect: Int) => { println("int assertion") value.equals(expect)} } implicit val StrEqual =new Assert[String] { def doAssert: (String, String) => Boolean = (value: String, expect: String) => { println("string assertion") value.equals(expect)} } } object Main extends App{ def Assertion[M](a: M, b: M)(implicit m: Assert[M]): Boolean = return m.doAssert(a, b) println(Assertion(1,1)) println(Assertion("1","1")) }