與 Java 同樣,Kotlin 也提供泛型,爲類型安全提供保證,消除類型強轉的煩惱。java
class DemoClass<T>(date: T) {//date是任意類型的,避免強轉 var todayDate=date }
//指定泛型date爲String,三種建立方法 val demo1: DemoClass<String> = DemoClass<String>("2018-01-27") val demo2: DemoClass<String> = DemoClass("2018-01-27") val demo3 = DemoClass("2018-01-27")
//指定泛型date爲Int,三種建立方法 val demo1: DemoClass<Int> = DemoClass<Int>(20180127) val demo2: DemoClass<Int> = DemoClass(20180127) val demo3 = DemoClass(20180127)
fun <T> showMsg(msg: T) { }
val msg = showMsg("泛型的使用") val msg1 = showMsg(200) val msg2 = showMsg<String>("指定返回類型")
fun <T> showPrint(printMsg: T) { when (printMsg) { is Int -> println("printMsg是Int類型:$printMsg") is String -> println("printMsg是String類型:$printMsg") else -> println("printMsg類型不是Int也不是String:$printMsg") } } fun main() { showMsg(100) showMsg("2017-01-27") showMsg(true) }
fun <T : Comparable<T>> sort(list: List<T>) {//上界約束 } fun main() { sort(listOf(1, 2, 3))//正確 sort(listOf("1", "2", "3"))//正確 sort(listOf(HashMap<Int,String>))//錯誤, HashMap<Int, String> 不是 Comparable<HashMap<Int, String>> 的子類型 }
//多個約束,T有多個上限 , where T:類型,T:類型 fun <T> getBetterBig(list: Array<T>, threhold: T): List<T> where T : Number, T : Comparable<T> { return list.filter { it >= threhold }.sorted() }
//建立兩個類,繼承關係 open class Person(name: String) open class Student(name: String) : Person("PersonA") class Teacher(name: String) : Student("StudentA") fun main() { var person = Person("PersonA") var personList: ArrayList<Person> = arrayListOf(person) var student = Student("StudentA") var studentList: ArrayList<Student> = arrayListOf(student) var teacher = Teacher("TeacherA") var teacherList: ArrayList<Teacher> = arrayListOf(teacher) for (name in personList.withIndex()) { println("name is $name")//輸出:name is PersonA } for (name in studentList.withIndex()) { println("name is $name")//輸出:name is StudentA } for (name in teacherList.withIndex()) { println("name is $name")//輸出:name is TeacherA } person = student//正確,由於 Student 是 Person 的子類 /* 編譯報錯,類型不匹配:Required ArrayList<Person> Found ArrayList<Student> 這是由於,雖然 Student 是 Person 的子類,可是 ArrayList<Student> 並非 ArrayList<Person> 的子類 */ personList = studentList//錯誤 }
fun main() { var person = Person("PersonA") var personList: ArrayList<out Person> = arrayListOf(person)//使用 out 修飾符,限定類型上限 var student = Student("StudentA") var studentList: ArrayList<Student> = arrayListOf(student) personList = studentList//編譯正確,這是由於 ArrayList<out Person> 限定了子類的上限爲 Person for (name in personList.withIndex()) { println("name is $name")//輸出:name is StudentA } }
fun main() { var person = Person("PersonA") var personList: ArrayList<Person> = arrayListOf(person) var student = Student("StudentA") var studentList: ArrayList<Student> = arrayListOf(student) var teacher = Teacher("TeacherA") var teacherList: ArrayList<Teacher> = arrayListOf(teacher) /* 如下兩種均報類型不匹配錯誤, */ teacherList = personList//Required ArrayList<Teacher> Found ArrayList<Person> teacherList = studentList//Required ArrayList<Teacher> Found ArrayList<Student> }
fun main3() { val person = Person("PersonA") val personList: ArrayList<Person> = arrayListOf(person) val student = Student("StudentA") val studentList: ArrayList<Student> = arrayListOf(student) val teacher = Teacher("TeacherA") var teacherList: ArrayList<in Teacher> = arrayListOf(teacher)// <in Teacher> 就是容許 Teacher 的超類類型下限爲 Teacher for (name in teacherList.withIndex()) { println("name is $name")//輸出:name is TeacherA } teacherList = personList for (name in teacherList.withIndex()) { println("name is $name")//輸出:name is PersonA } teacherList = studentList for (name in teacherList.withIndex()) { println("name is $name")//輸出:name is StudentA } }
再來理解消費者 in 只能用做輸入和 生產者 out 只能用做輸出的概念:git
不使用 in 和 out 修飾時github
open class Person(name: String) { var myName = "Siberiadante" } class Student(name: String) : Person("PersonA") fun main() { val person = Person("PersonA") var personList: ArrayList<Person> = arrayListOf(person) val student = Student("StudentA") var studentList: ArrayList<Student> = arrayListOf(student) personList.add(student)//set 設置值,編譯經過 personList[0].myName// get 取值,編譯經過 }
做爲 < out T>的類型,因爲全部類型均爲T的下限,沒法得知其肯定的類型,因此不能使用 set 方法,只能 get安全
fun main() { val person = Person("PersonA") var personList: ArrayList<out Person> = arrayListOf(person) val student = Student("StudentA") var studentList: ArrayList<Student> = arrayListOf(student) /* prohibits(禁止) use of public open fun add(element:E) ! */ personList.add(student)// set 設置值,編譯不經過 personList[0].myName// get 取值,編譯經過 }
做爲 < in T>的類型函數
fun main() { val person = Person("PersonA") var personList: ArrayList<in Person> = arrayListOf(person) val student = Student("StudentA") var studentList: ArrayList<Student> = arrayListOf(student) personList.add(student)//set 設置值,編譯經過 /* Unresolved reference : name, */ personList[0].myName// get 取值,編譯不經過 }
var list:ArrayList<*> = arrayListOf(100)
fun main() { val person = Person("PersonA") val student = Student("StudentA") val studentList: ArrayList<Student> = arrayListOf(student) /* 至關於 var personList: ArrayList<out Person> = studentList */ var personList: ArrayList<*> = studentList }
fun main9() { val person = Person("PersonA") val personList: ArrayList< Person> =arrayListOf(person) val student = Student("StudentA") /* 至關於 val studentList:ArrayList<in Student> =personList */ val studentList:ArrayList<*> =personList }