パラメータの1つまたは複数のタイプで、一般的なクラスの大規模なデータ・ライン学習Scalaのシリーズを共有するのが良いプログラマは一般的なものです。
ジェネリッククラス定義:
//クラスが持つパラメータAの型を定義
クラススタック[A] {
リスト[A] =無記号:プライベートVAR要素
//ジェネリックメソッド
DEFプッシュ(X:A)X :: = {要素エレメント}
DEF PEEK。 elements.head =
DEF POP():A = {
ヴァルcurrentTop = PEEK
要素= elements.tail
currentTop
}
}
ジェネリッククラスを使用して、代わりのパラメータ特定のタイプAのタイプ
ヴァルスタック=新しいスタック[INT]
stack.push(1)
stack.push(2)
のprintln(stack.pop)//プリント2
のprintln(stack.pop)//プリント1
1.共変
タイプAとB、AがBのサブタイプである、リスト[A]はリスト[B]サブタイプである:Aは、共変の意味である場合、List型[+ A]を定義します。
抽象クラス動物{
DEFパラメータname:String
}
ケースクラスキャット(名:文字列)動物延び
:動物を拡張する場合クラス犬(文字列名)
プロシージャ・コールを、次の時に型パラメータはあまり成功し、共変であるため、Scalaのジェネリッククラスライブラリは、密閉された抽象クラスリストの[+ A]を持っています。
{アプリケーションオブジェクトを拡張CovarianceTest
//定義するパラメータは、リスト[動物]タイプ
DEF printAnimalNames(動物:リスト[動物]):単位= {
animals.foreach = {動物>
のprintln(animal.name)
}
}
CATSヴァル:リスト[猫] =リスト(キャット( "ひげ")、猫( "トム"))
ヴァル犬:リスト[犬] =リスト(ドッグ( "ファイド")、犬( "レックス"))
// [猫] List型のパラメータを渡し
printAnimalNames(CATS)
//ウィスカ
//トムは
[犬] List型のパラメータを渡す//
printAnimalNames(イヌ)
//ファイド
//レックス
}
前記インバータは、
Aは、インバータである場合を意味し、タイプライター[-A]を定義する:タイプA及びBは、AがBのサブタイプライターである[B]はライター[A]サブタイプです。
抽象クラス動物{
DEFパラメータname:String
}
ケースクラスキャット(名:文字列)動物延び
:動物を拡張する場合クラス犬(文字列名)
情報印刷の上記動作にクラス定義
抽象クラスプリンタ[-A] {
DEF(値:A):印刷ユニット
}
クラスAnimalPrinterは{プリンタ[動物]延び
単位= DEF(:動物動物)を印刷
(:+ animal.name "動物の名前である")のprintlnを
}
クラスCatPrinterプリンター[猫] {延び
単位= DEF(:猫の猫)を印刷
のprintln( "猫の名前は" + cat.nameを)
}
インバータのテスト
オブジェクトContravarianceTestが延びるアプリ{
ヴァルmyCat:猫=猫(「ブーツ」)
//型プリンタのパラメータを定義する[猫]
DEF printMyCat(プリンタ:プリンタ[猫]):単位= {
Printer.Print(myCat)
}
ヴァルcatPrinter:プリンタ[猫]新しいCatPrinter =
ヴァルanimalPrinterを:プリンタ[動物]新しいAnimalPrinterを=
printMyCat(catPrinter)
//型パラメータを渡すことができるプリンタ[動物]
printMyCat(animalPrinter)
}
3.上限
上限が定義されている:T <:A、Tは、変数の型タイプのものでなければならないサブクラスを表します
抽象クラス動物{
DEF名:文字列
}
抽象クラスペット動物を{}延び
クラス猫のペット{延び
オーバーライドDEF名:文字列=「猫」
}
クラス犬はペット延び{
オーバーライドDEF名:文字列=「犬」
}
ライオンは動物{クラス延び
:文字列= "ライオン"オーバーライドDEF名
}
//ペット型パラメータタイプは、のサブクラスとなる
クラスPetContainer [P <:ペット](P:P){
DEF PET:P = P
}
//犬ペットの種類がのサブクラスである
ヴァルdogContainer =新しい新しいPetContainer [犬](新しい新しい犬)
//猫のペットの種類は、サブクラスである
ヴァルcatContainer =新しい新しいPetContainer [猫](新しい新しいCAT)
コンパイル//ないペットライオン型のサブクラスは、合格
// valをlionContainer =新しいPetContainer [ライオン ](新しいライオン)
4.低いバウンド
構文B>:被験者または抽象タイプBタイプAのタイプを示すパラメータは、親クラスです。典型的には、Aは、Bは、メソッドのパラメータの型で、パラメータークラスタイプです。
コード上、共変としてタイプBため、関数のパラメータは通過しないコンパイラをもたらす、インバータ型を必要としました。この問題を解決するために、我々は、下限の概念を使用する必要があります。
形質ノード[+のB] {
DEFプリペンド[U>:B](ELEM:U):ノード[U]
}
ケースクラスListNode [+ B](H:B、T:ノード[B])をノード[B] {延び
:(ELEM:U):ListNode [U] = ListNode(ELEM、この)DEF先頭に付加[B U>]を
DEFヘッド:B = Hの
DEFテール:ノード[B] = T
}
ケースクラス無記号は[+ B]()ノード[B] {延び
:(ELEM:U):ListNode [U] = ListNode(ELEM、この)DEF先頭に付加[B U>]
}を
テスト
形質バード
ケースクラスAfricanSwallow()はバード延び
場合クラスEuropeanSwallowを()鳥を拡張します
ヴァルafricanSwallowList = ListNode [AfricanSwallow(AfricanSwallow()、無記号())
ヴァルbirdList:ノード[鳥] = africanSwallowList
birdList.prepend(新しいEuropeanSwallow)
5地平線(ビューの境界)
注:時代遅れ、あなたは理解することができます
水平線が定義される:<%のB、A、タイプB`のサブクラスでなければならないタイプの変数を表し、AまたはBは、暗黙的に変換することができます
クラスPair_Int [T <%匹敵[T](valが最初:T、ヴァル秒:T){
DEF大きく= IF(first.compareTo(その2)> 0)他の第二
}
クラスPair_Better [T <%秩序[T](ヴァル最初:T、ヴァル秒:T){
DEF小さく= IF(第<秒)最初他二
}
オブジェクトView_Bound {
メインDEF(引数:配列[文字列]){
//ペア[文字列]匹敵[T]のサブタイプであるので、これが文字列compareToメソッド
ヴァルPair_Int新しい新しいペアが=(「スパーク」、「Hadoopの」);
のprintln(対.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)
}
}
図6は、コンテキスト(コンテキスト境界)を規定する
Tとして定義されたコンテキストの形で:M、Mは、一般的なクラスである必要があり、値が暗黙M [T]はなければなりません。
クラスPair_Context [T:注文(ヴァル最初:T、ヴァル秒:T){
DEF小さい(暗黙ORD:注文[T])=
(ord.compare(第一、第二)<0)他の第二場合
}
オブジェクトContext_Bound {
DEFメイン(引数:配列[文字列]){
val pair = new Pair_Context("Spark", "Hadoop")
println(pair.smaller)
val int = new Pair_Context(3, 5)
println(int.smaller)
}
}