Dalam penerapan generic, kita bisa membatasi tipe apa saja yang dapat digunakan sebagai parameter. Untuk menentukkan batasan tersebut, bisa dengan menambahkan tanda titik dua (:) setelah tipe parameter yang kemudian diikuti oleh tipe yang akan dijadikan batasan. Contohnya seperti berikut:
1. class ListNumber<T : Number> : List<T>{ 2. override fun get(index: Int): T { 3. /* .. */ 4. } 5. }
Pada kode di atas kita telah menentukan Number sebagai batasan tipe argumen. Dengan begitu, kita hanya bisa memasukkan tipe argumen Number pada kelas ListNumber. Dan ketika kita memasukkan selain Number, maka akan terjadi eror seperti berikut:
1. fun main() { 2. val numbers = ListNumber<Long>() 3. val numbers2 = ListNumber<Int>() 4. val numbers3 = ListNumber<String>() // error : Type argument is not within its bounds 5. } 6. 7. class ListNumber<T : Number> : List<T>{ 8. override fun get(index: Int): T { 9. /* .. */ 10. } 11. }
Contoh lain dari constraint type parameter adalah seperti berikut:
1. fun <T : Number> List<T>.sumNumber() : T { 2. /* .. */ 3. }
Fungsi di atas merupakan extensions function dari kelas List yang mempunyai tipe parameter. Sama seperti deklarasi generic pada sebuah fungsi, tipe parameter T pada fungsi tersebut juga akan digunakan sebagai receiver dan return type. Perbedaannya terletak pada cara memanggilnya. Fungsi tersebut akan tersedia pada variabel List dengan tipe argumen yang memiliki supertype Number.
1. fun main() { 2. val numbers = listOf(1, 2, 3, 4, 5) 3. numbers.sumNumber() 4. val names = listOf("dicoding", "academy") 5. names.sumNumber() // error : inferred type String is not a subtype of Number 6. } 7. 8. fun <T : Number> List<T>.sumNumber() : T { 9. /* .. */ 10. }