scala 上界 <:, 下界>:, 视界 <%, 边界 :, 协变 +T, 逆变-T
概述
上界 (<:) 下界(>:) 是類型約束范疇,用來(lái)約束對(duì)象的子類是誰(shuí),父類是誰(shuí)
協(xié)變 (+T) 逆變(-T)是泛型范疇,主要用于集合類型變量賦值。
視界 (<%) 邊界( :)是隱式調(diào)用的簡(jiǎn)寫(xiě)。
上界 (<:) 下界(>:)
上界:要求對(duì)象必須是某一個(gè)對(duì)象的子類,因?yàn)樽宇悤?huì)繼承父類的屬性和方法,所以父類的方法和屬性這路都可以用。
trait A {def func()}class B extends A {override def func(): Unit = {println("i am b")}}class C extends A {override def func(): Unit = {println("i am c")}}def test[T <: A](obj: T): Unit = {obj.func()}test(new B()) // i am btest(new C()) // i am c下界:要求對(duì)象必須是某一個(gè)對(duì)象的父類。主要用在已知某一個(gè)具體類型,但是要給它賦值給另一個(gè)變量,該變量必須是具體類型的父類型才行。
舉例:
對(duì)于下面的例子,我們要把元素B放到一個(gè)集合中,這個(gè)集合必須是類型B父類容器才行。這里就是B是已知類型,集合類型未知。
協(xié)變 (+T) 逆變(-T)
逆變協(xié)變指的是類型T和包裝類型直接的關(guān)系。
有兩個(gè)類如下所示:
假設(shè)有個(gè)包裝類型F[T]
class F[T]現(xiàn)在我們生產(chǎn)一個(gè)F[B]實(shí)例,然后賦值給F[A]類型的變量.就會(huì)報(bào)錯(cuò)。因?yàn)镕[B]并不是F[A]的子類。
val a:F[A] = new F[B]() // error所以這個(gè)時(shí)候才會(huì)需要逆變和協(xié)變。
協(xié)變:子類的包裝類型也是父類包裝類型的子類
逆變:子類的包裝類型是父類包裝類型的父類
class G[-T] // 逆變val b: G[B] = new G[A]() // 正確一個(gè)比較經(jīng)典的例子是:scala 函數(shù)的定義.scala中所有的函數(shù),參數(shù)都是逆變的,返回值都是協(xié)變的。 trait Function[-T1,+T2].也就是說(shuō)一個(gè)函數(shù)要賦值給一個(gè)函數(shù)類型變量。這個(gè)函數(shù)的參數(shù)必須是函數(shù)變量參數(shù)的父類,返回值必須是函數(shù)變量返回值的子類。
trait A {def func()}class B extends A {override def func(): Unit = {println("i am b")}}class C extends B {}val func: B => B = (a: A) => { new C() } // 把 A=>C類型的函數(shù)賦值給B=>B類型的變量視界 <%, 邊界 :
視圖和邊界看到的比較多,但是功能比較強(qiáng)大,也容易被誤解。比如 ( : )就經(jīng)常會(huì)被誤以為是上界和下屆的一種。
視界 <%
視界只是一種隱式類型函數(shù)的簡(jiǎn)寫(xiě)。如果我們需要一個(gè)Fruits類型的隱式參數(shù),但是我們只有一個(gè) T 類型,這時(shí)就可以用視界。他要求想使用這個(gè)函數(shù),必須提供一個(gè)由T => Fruits的隱式調(diào)用。 比如下面:
scala> case class Fruits(name: String) defined class Fruitsscala> def getFruits[T <% Fruits](value: T): Fruits = value getFruits: [T](value: T)(implicit evidence$1: T => Fruits)Fruits等價(jià)于scala> def getFruits[T](value: T)(implicit evidence: T => Fruits): Fruits = evidence(value) getFruits: [T](value: T)(implicit evidence: T => Fruits)Fruits邊界 :
邊界相對(duì)來(lái)將應(yīng)用場(chǎng)景比較多一些。下面有個(gè)函數(shù)anothr,需要一個(gè)隱式參數(shù)。我們?cè)趂unc中調(diào)用了這個(gè)方法,但是我們并沒(méi)有提供隱式參數(shù)。這就和視圖有點(diǎn)類似了。在視圖中要求傳入一個(gè)隱式函數(shù),但這里是要求傳入一個(gè)隱式類型。
class F[T]def another[T](elem: T)(implicit f: F[T]) = {// do nothing }def func[T: F](elem: T): Unit = {another(elem) }scala> def func[T: F](elem: T): Unit = {another(elem)}func: [T](elem: T)(implicit evidence$1: F[T])Unit // 使用 scala> func(1)(new F[Int]()) 或則 scala> func(1)(new F()) //自行推斷有一個(gè)比較經(jīng)典的例子,利用這個(gè)方法可以實(shí)現(xiàn)隱式泛型
import scala.reflect.runtime.universe._typeOf函數(shù)需要傳入一個(gè)隱式類型TypeTag[T] // def typeOf[T](implicit ttag: TypeTag[T]): Type = ttag.tpedef getTypeTag[T: TypeTag](obj: T) = typeOf[T] // 我們調(diào)用的時(shí)候也沒(méi)有傳入隱式類型,因?yàn)閟cala運(yùn)行環(huán)境中會(huì)自定存儲(chǔ)。 getTypeTag(1)總結(jié)
以上是生活随笔為你收集整理的scala 上界 <:, 下界>:, 视界 <%, 边界 :, 协变 +T, 逆变-T的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Windows To Go常见问题
- 下一篇: 怎么用计算机表达爱意,不知道如何向心仪的