多态的类型(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")) }