深圳大資料學習:泛型--【千鋒】
深圳大資料學習: 泛型--【千鋒】
帶有一個或多個型別引數的類是泛型的。
泛型類的定義:
//
帶有型別引數
A
的類定義
class
Stack[A] {
private
var
elements: List[A] = Nil
//
泛型方法
def
push
(x: A) { elements = x :: elements }
def
peek: A = elements.
head
def
pop
(): A = {
val
currentTop = peek
elements = elements.
tail
currentTop
}
}
泛型類的使用,用具體的型別代替型別引數A。
val
stack =
new
Stack[Int]
stack.
push
(
1
)
stack.
push
(
2
)
println
(stack.
pop
)
// prints 2
println
(stack.
pop
)
// prints 1
8.1. 協變
定義一個型別List[+A],如果A是協變的,意思是:對型別A和B,A是B的子型別,那麼List[A]是List[B]的子型別。
abstract
class
Animal {
def
name: String
}
case
class
Cat
(name: String)
extends
Animal
case
class
Dog
(name: String)
extends
Animal
Scala標準庫有一個泛型類sealed abstract class List[+A],因為其中的型別引數是協變的,那麼下面的程式呼叫時成功的。
object
CovarianceTest
extends
App {
//
定義引數型別
List[Animal]
def
printAnimalNames
(animals: List[Animal]): Unit = {
animals.
foreach
{ animal =>
println
(animal.
name
)
}
}
val
cats: List[Cat] = List(
Cat
(
"Whiskers"
),
Cat
(
"Tom"
))
val
dogs: List[Dog] = List(
Dog
(
"Fido"
),
Dog
(
"Rex"
))
//
傳入引數型別為
List[Cat]
printAnimalNames
(cats)
// Whiskers
// Tom
//
傳入引數型別為
List[Dog]
printAnimalNames
(dogs)
// Fido
// Rex
}
8.2. 逆變
定義一個型別Writer[-A],如果A是逆變的,意思是:對型別A和B,A是B的子型別,那麼Writer[B]是Writer[A]的子型別。
abstract
class
Animal {
def
name: String
}
case
class
Cat
(name: String)
extends
Animal
case
class
Dog
(name: String)
extends
Animal
定義對應上述類進行操作的列印資訊類
abstract
class
Printer[-A] {
def
print
(value: A): Unit
}
class
AnimalPrinter
extends
Printer[Animal] {
def
print
(animal: Animal): Unit =
println
(
"The animal's name is: "
+ animal.
name
)
}
class
CatPrinter
extends
Printer[Cat] {
def
print
(cat: Cat): Unit =
println
(
"The cat's name is: "
+ cat.
name
)
}
逆變的測試
object
ContravarianceTest
extends
App {
val
myCat: Cat =
Cat
(
"Boots"
)
//
定義引數型別為
Printer[Cat]
def
printMyCat
(printer: Printer[Cat]): Unit = {
printer.
print
(myCat)
}
val
catPrinter: Printer[Cat] =
new
CatPrinter
val
animalPrinter: Printer[Animal] =
new
AnimalPrinter
printMyCat
(catPrinter)
//
可以傳入引數型別為
Printer[Animal]
printMyCat
(animalPrinter)
}
8.3. 上界
上界定義: T <: A ,表示型別變數 T 必須是 型別 A 子類
abstract
class
Animal {
def
name: String
}
abstract
class
Pet
extends
Animal {}
class
Cat
extends
Pet {
override
def
name: String =
"Cat"
}
class
Dog
extends
Pet {
override
def
name: String =
"Dog"
}
class
Lion
extends
Animal {
override
def
name: String =
"Lion"
}
//
引數型別須是
Pet
型別的子類
class
PetContainer[P <: Pet](p: P) {
def
pet: P = p
}
//Dog
是
Pet
型別的子類
val
dogContainer =
new
PetContainer[Dog](
new
Dog)
//Cat
是
Pet
型別的子類
val
catContainer =
new
PetContainer[Cat](
new
Cat)
//Lion
不是
Pet
型別的子類,編譯通不過
// val lionContainer = new PetContainer[Lion](new Lion)
8.4. 下界
語法 B >: A 表示引數型別或抽象型別 B 須是型別A的父類。通常,A是類的型別引數,B是方法的型別引數。
上面這段程式碼,因為作為協變型別的B,出現在需要逆變型別的函式引數中,導致編譯不透過。解決這個問題,就需要用到下界的概念。
trait Node[+B] {
def prepend[U >: B](elem: U): Node[U]
}
case class ListNode[+B](h: B, t: Node[B]) extends Node[B] {
def prepend[U >: B](elem: U): ListNode[U] = ListNode(elem, this)
def head: B = h
def tail: Node[B] = t
}
case class Nil[+B]() extends Node[B] {
def prepend[U >: B](elem: U): ListNode[U] = ListNode(elem, this)
}
測試
trait Bird
case class AfricanSwallow() extends Bird
case class EuropeanSwallow() extends Bird
val africanSwallowList= ListNode[AfricanSwallow](AfricanSwallow(), Nil())
val birdList: Node[Bird] = africanSwallowList
birdList.prepend(new EuropeanSwallow)
8.5 視界 (view bounds)
注意 :已過時,瞭解即可
視界定義: A <% B ,表示型別變數 A 必須是 型別 B`的子類,或者A能夠隱式轉換到B
class
Pair_Int[T <% Comparable[T]] (
val
first: T,
val
second: T){
def
bigger =
if
(first.
compareTo
(second) >
0
) first
else
second
}
class
Pair_Better[T <% Ordered[T]](
val
first: T,
val
second: T){
def
smaller =
if
(first < second) first
else
second
}
object
View_Bound {
def
main
(args: Array[String]) {
//
因為
Pair[String]
是
Comparable[T]
的子型別
,
所以
String
有
compareTo
方法
val
pair =
new
Pair_Int
(
"Spark"
,
"Hadoop"
);
println
(pair.
bigger
)
/**
*
Scala
語言裡
Int
型別沒有實現
Comparable
;
*
那麼該如何解決這個問題那
;
*
在scala
裡
RichInt
實現了
Comparable
,
如果我們把int
轉換為
RichInt
型別就可以這樣例項化了
.
*
在scala
裡
<
%
就起這個作用
,
需要修改Pair
裡的
<:
為<%
把T
型別隱身轉換為
Comparable[Int]
* String
可以被轉換為RichString.
而RichString
是
Ordered[String]
的子類.
*
/
val pair_int
=
new
Pair_Int
(3
,45)
println
(pair_int.bigger)
val pair_better
=
new
Pair_Better
(39
,5)
println
(pair_better.smaller)
}
}
8.6 上下文界定 (context bounds)
上下文界定的形式為 T : M, 其中M 必須為泛型類, 必須存在一個M[T]的隱式值.
class
Pair_Context[T : Ordering](
val
first: T,
val
second: T){
def
smaller
(
implicit
ord: Ordering[T]) =
if
(ord.
compare
(first, second) <
0
) first
else
second
}
object
Context_Bound {
def
main
(args: Array[String]) {
val
pair =
new
Pair_Context
(
"Spark"
,
"Hadoop"
)
println
(pair.
smaller
)
val
int
=
new
Pair_Context
(
3
,
5
)
println
(
int
.
smaller
)
}
}
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69947096/viewspace-2660984/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 深圳大資料學習:方法的巢狀--【千鋒】大資料巢狀
- 深圳大資料學習:高階函式--【千鋒】大資料函式
- 深圳Java培訓學習:MyBatis Plus 介紹--【千鋒】JavaMyBatis
- 深圳Java學習:小白速懂Https協議-千鋒JavaHTTP協議
- 深圳雲端計算培訓學習:Apache 訪問控制--【千鋒】Apache
- 深圳Web前端培訓學習:js中的模組化--【千鋒】Web前端JS
- 深圳Python培訓學習:Python3 簡介–[千鋒]Python
- 深圳軟體測試培訓學習:Java Random介紹--【千鋒】Javarandom
- 深圳Java學習:MyBatis為什麼在國內相當流行?-千鋒JavaMyBatis
- 深圳軟體測試培訓學習:Java連線MySQL--【千鋒】JavaMySql
- 深圳Web前端學習:如何給網頁劃分合適的結構--【千鋒】Web前端網頁
- 深圳雲端計算培訓學習:部署網校系統 edusoho--【千鋒】
- 深圳Web前端學習:學 Web 前端開發,培訓還是自學靠譜?-千鋒Web前端
- 深圳Web前端學習:前端工程師到底要不要學習演算法知識?--【千鋒】Web前端工程師演算法
- 大資料和雲端計算的關係是什麼?-千鋒深圳雲端計算培訓大資料
- 深圳雲端計算培訓學習:雲端計算正在殺死運維嗎?–【千鋒】運維
- 深圳雲端計算培訓學習:女生做雲端計算運維容易嗎?–【千鋒】運維
- 深圳java培訓:構建xml文件--【千鋒】JavaXML
- 好程式設計師大資料學習路線分享Scala系列之泛型程式設計師大資料泛型
- C#泛型學習C#泛型
- 泛型學習筆記泛型筆記
- java泛型學習(1)Java泛型
- 深圳軟體測試培訓學習:Android常用自動化測試工具【千鋒】Android
- 深圳Web前端培訓學習:5G對Web前端發展的影響--【千鋒】Web前端
- 深圳雲端計算培訓學習:構建企業級WIKI及工單系統 --【千鋒】
- 學習Rust泛型與特性Rust泛型
- 深圳軟體測試學習:寫不好測試用例是因為沒時間嗎?【千鋒】
- 如何快速入門Spark——千鋒大資料教程免費領取Spark大資料
- 深圳軟體測試學習:如何在Android手機上進行自動化測試【千鋒】Android
- TypeScript學習(四)—— 介面和泛型TypeScript泛型
- 想去學習千鋒PHP,PHP究竟有哪些優點?PHP
- 大資料學習資料大資料
- C#學習 [型別系統] 泛型(16)C#型別泛型
- 大資料學習大資料
- java入門基礎學習----泛型Java泛型
- java基礎學習之十三:泛型Java泛型
- PLSQL學習——資料型別SQL資料型別
- Python學習系列之七大資料型別Python大資料資料型別