scala 類型參數(shù)庐完、界定、類型約束

類徘熔、特質(zhì)门躯、方法和函數(shù)都可以有類型參數(shù)

將類型參數(shù)放置在名稱之后,以方括號(hào)括起來

參數(shù)類型(不能什么都傳酷师,要加限定)

對(duì)于參數(shù)類型的 class 實(shí)際類型會(huì)在new對(duì)象時(shí)推斷

例如:class Pair[T, S](val first: T, val second: S)

val?p =?new?Pair(42,?"String")

參數(shù)類型界定

1讶凉、<: 和 >: (我定義為 “純子類界定”)

class Pair[T](val first: T, val second: T)

它要求 兩個(gè)參數(shù)類型相同

添加一個(gè)方法,返回較小的那個(gè)值:

? class Pair[T](val first: T, val second: T) {

? ? def smaller = if (first.compareTo(second) < 0) first else second

? }

這是錯(cuò)的山孔,因?yàn)槲覀儾⒉恢纅irst是否有compareTo方法懂讯,所以添加一個(gè)上界T<:Comparable[T]? (必須是以可比較的類型)

? class Pair[T <: Comparable[T]](val first: T, val second: T) {

? ? def smaller = if (first.compareTo(second) < 0) first else second

? }

原來給T什么都可以傳,現(xiàn)在就不行了饱须。

你也可以為類型指定一個(gè)下界(也就是要求是子類)域醇。

舉例,把第一個(gè)組件替換為子類蓉媳。

? class Person? class Student extends Person

? class Pair[T](val first: T, val second: T) {

? ? def replaceFirst(newFirst: T) = new Pair[T](newFirst, second)

? }

假定我們有一個(gè)Pair[Person]譬挚,我們想用Student 替換第一個(gè)類型,實(shí)際上這樣是不可行的酪呻,因?yàn)門必須一致减宣。因此,在函數(shù)后面定義下界玩荠。

? class Pair[T](val first: T, val second: T) {

? ? def replaceFirst[R >: T](newFirst: R) = new Pair[R](newFirst, second)

? }

2漆腌、<% 視圖界定 (我定義為:“含隱式條件的子類界定”)

前面有一個(gè)帶上界的示例:

把 前面的例子 class?Pair[T?<:?Comparable[T]]

如果你new一個(gè)Pair(4,2),編譯器會(huì)報(bào)錯(cuò)阶冈,Scala的Int類型并沒有實(shí)現(xiàn)Comparable闷尿。

解決辦法是使用視圖界定:

? class Pair[T <% Comparable[T]](val first: T, val second: T) {

? ? def smaller = if (first.compareTo(second) < 0) first else second

? }

<%?意味著 T 可以被隱式轉(zhuǎn)換成Comparable[Int]。

隱式類型轉(zhuǎn)換女坑,Int 轉(zhuǎn) RichInt 填具,RichInt實(shí)現(xiàn)了Comparable[Int]

3、T:M 上下文界定 (我定義為:“含隱式的子類界定”)

其中M是另一個(gè)泛型類。它要求必須存在一個(gè)類型為M[T]的“隱式值”劳景。也就是說必須把這個(gè)類型放在另外一個(gè)類型里

? class Pair[T : Ordering](val first: T, val second: T) {

? ? def smaller(implicit ord: Ordering[T]) =

? ? ? if (ord.compare(first, second) < 0) first else second

? }

4誉简、<% 上Manifest 上下文界定

Manifest were added specially to handle arrays

要實(shí)例化一個(gè)泛型的Array[T],我們需要一個(gè)Manifest[T]對(duì)象盟广。要想讓基本類型的數(shù)組能夠正常工作的話闷串,這是必須的。舉例來說筋量,如果T是Int烹吵,你會(huì)希望虛擬機(jī)中對(duì)應(yīng)的是一個(gè)int[]數(shù)組。在Scala中毛甲,Array只不過是類庫提供的一個(gè)類年叮,編譯器并不對(duì)它做特殊處理。如果你要編寫一個(gè)泛型函數(shù)來構(gòu)造泛型數(shù)組的話玻募,你需要傳入這個(gè)Manifest對(duì)象來幫忙。由于它是構(gòu)造器的隱式參數(shù)一姿,你可以用上下文界定:

? def makePair[T: Manifest](first: T, second: T) = {

? ? val r = new Array[T](2)

? ? r(0) = first

? ? r(1) = second

? }

類型約束

類型約束提供的是另一個(gè)限定類型的方式七咧。總共有三種關(guān)系可供使用:

T=:=U?測(cè)試T是否等于U

T<:

T<%

要使用這樣一個(gè)約束叮叹,需要添加“隱式類型證明參數(shù)”:

class Pair[T](val first: T, val second: T)(implicit ev: T?<:<?Comparable[T])

不過在上面的例子中艾栋,使用類型約束并沒有比類型變量界定class Pair[T<:Comparable[T]]有更多的優(yōu)點(diǎn)。不過在某些場(chǎng)景下蛉顽,類型約束會(huì)很有用蝗砾。

類型約束讓你可以在泛型類中定義只能在特定條件下使用的方法,示例如下:

? class Pair[T](val first: T, val second: T) {

? ? def smaller(implicit ev: T <:< Comparable[T]) =

? ? ? if (first.compareTo(second) < 0) first else second

? }

? val p1 = new Pair("a", "b") //a

你可以構(gòu)造出Pair[File]携冤,盡管File并不是帶有先后次序的悼粮。只有當(dāng)你調(diào)用smaller方法的時(shí)候才會(huì)報(bào)錯(cuò)。

型變:協(xié)變和逆變

class Personclass Student extends Person

def?makeFriends(p:?Pair[Person]) //此函數(shù)要對(duì)Pair[Person]做某種處理曾棕,但是要調(diào)用Student里的方法

我們知道扣猫,因?yàn)殡m然Student是Person的子類,但是Pair[Student]和Pair[Person]一點(diǎn)關(guān)系都沒有翘地。如果你想要這樣的關(guān)系申尤,則必須在定義Pair類的時(shí)候表明這一點(diǎn):

class Pair[+T](val first: T, val second: T)// 可以協(xié)變,表明衙耕,可以用子類的方法

+號(hào)意味著如果Student是Person的子類昧穿,那么Pair[Student]也是Pair[Person]的子類。

也可以有另一個(gè)方向的型變橙喘∈蓖遥考慮泛型類型Friend[T],表示希望與類型T的人成為朋友的人:

? trait Friend[-T] {

? ? def befriend(someone: T)

? }

現(xiàn)在假定有一個(gè)函數(shù):

? def makeFriendWith(s: Student, f: Friend[Student]) {

? ? f.befriend(s)

? }

你能用Friend[Person]作為參數(shù)調(diào)用它嗎渴杆?也就是說寥枝,如果你有:

? class Person extends Friend[Person]

? class Student extends Person? val susan = new Student? val fred = new Person

函數(shù)調(diào)用makeFriendWith(susan,fred)能成功嗎宪塔?看上去應(yīng)該可以,因?yàn)閒red想和任何人叫交朋友囊拜,他也一定會(huì)和susan交朋友某筐。注意到這個(gè)時(shí)候,類型變化的方向和子類型方向是相反的冠跷。Student是Person的子類南誊,但是Friend[Student]是Friend[Person]的超類。這種情況下蜜托,需要將類型參數(shù)聲明為逆變的抄囚。

協(xié)變、逆變橄务,特質(zhì)的定義會(huì)使用到它

trait Function1 [-T1, +R] extends AnyRef

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末幔托,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蜂挪,更是在濱河造成了極大的恐慌重挑,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件棠涮,死亡現(xiàn)場(chǎng)離奇詭異谬哀,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)严肪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門史煎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人驳糯,你說我怎么就攤上這事篇梭。” “怎么了结窘?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵很洋,是天一觀的道長。 經(jīng)常有香客問我隧枫,道長喉磁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任官脓,我火速辦了婚禮协怒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘卑笨。我一直安慰自己孕暇,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著妖滔,像睡著了一般隧哮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上座舍,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天沮翔,我揣著相機(jī)與錄音,去河邊找鬼曲秉。 笑死采蚀,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的承二。 我是一名探鬼主播榆鼠,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼亥鸠!你這毒婦竟也來了妆够?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤负蚊,失蹤者是張志新(化名)和其女友劉穎责静,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盖桥,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年题翻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了揩徊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嵌赠,死狀恐怖塑荒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情姜挺,我是刑警寧澤齿税,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站炊豪,受9級(jí)特大地震影響凌箕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜词渤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一牵舱、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧缺虐,春花似錦芜壁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽顷牌。三九已至,卻和暖如春塞淹,著一層夾襖步出監(jiān)牢的瞬間窟蓝,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來泰國打工窖铡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留疗锐,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓费彼,卻偏偏與公主長得像滑臊,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子箍铲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • Scala與Java的關(guān)系 Scala與Java的關(guān)系是非常緊密的9途怼! 因?yàn)镾cala是基于Java虛擬機(jī)颠猴,也就是...
    燈火gg閱讀 3,452評(píng)論 1 24
  • 變量初始化可以用用 _ 作占位符关划,賦值為默認(rèn)值,字符串 null翘瓮,F(xiàn)loat贮折、Int、Double 等為 0var...
    FaDeo_O閱讀 923評(píng)論 0 0
  • 上界 case class Pair[T <: Comparable[T]](first: T, second: ...
    fengjixcuhui閱讀 426評(píng)論 0 0
  • 喜歡一個(gè)人,可以用一秒。遺忘一個(gè)人,則需一生艰管。愛一個(gè)人婚肆,可以付出一切的一切。不愛一個(gè)人,ta付出一切的一切,也不會(huì)...
    忘不掉的事閱讀 207評(píng)論 0 0
  • 今天翻到了08年的健身筆記,仔細(xì)想來腮出,已經(jīng)訓(xùn)練了10年整,假如問我最大收獲是什么拔创?我會(huì)用我的照片利诺,告訴各位 首先是...
    永遠(yuǎn)的mark閱讀 320評(píng)論 0 0