學習kotlin第13天_具體化的型別引數、內聯屬性、解構宣告、集合
繼續之前的坑,我原本不打算繼續看文件了,直接上手個小專案,但是專案中遇見個小問題,list似乎和java中的有區別。。。一查文件發現在後面。。。所以繼續踩坑。
坑1、有時候我們需要型別作為引數傳給函式,可以使用reified修飾符來限定型別引數,這樣就可以直接在函式內部訪問它了。此外,呼叫時可以直接傳入該型別引數。
inline fun <reified T> TreeNode.findParentOfType(): T? { var p = parent while (p != null && p !is T) { p = p.parent} return p as T?//如果沒有被標記為reified的話需要新增@Suppress("UNCHECKED_CAST")註解 } fun main(args: Array<String>) { val treeNode: TreeNode = MyTreeNode()//MyTreeNode類實現了TreeNode介面 treeNode.findParentOfType<MyTreeNode>() }
坑2、如果需要,可以對一個具體化的型別引數使用反射。
inline fun < reified T> membersOf() = T::class.members fun main(s: Array<String>) { println(membersOf<StringBuilder>().joinToString("\n")) }
坑3、inline可用於沒有幕後欄位的屬性的訪問器,即可以單獨標註訪問器也可以標註整個屬性。
val foo: Foo get() = Foo() var bar: Bar get() =...... inline set(v) {......} inline var bar2: Bar get() = ...... set(v) {......}
坑4、kotlin中使用協程掛起替代先從阻塞,在kotlin1.1中是實驗性的。suspend函式用於標記掛起函式。
。。。。。。看不懂,跳過。
坑5、之前講資料類的時候提到過資料類根據引數自動建立對應的component函式,可以把一個物件解構成多個變數。只要可以對它呼叫所需數量的component 函式,任何表示式都可以出現在解構宣告的右側。其中,component函式必須用operator標記。解構宣告也可以用在for迴圈中。
class User(var name: String = "", var age: Int = 0) { operator fun component1(): String { return name } operator fun component2(): Int { return age } override fun toString(): String { return "User(name='$name', age=$age)" } } fun main(args: Array<String>) { val u: User = User() val (name, age) = u println(name) println(age) val p = listOf(User("Door", 22 ), User("Green", 30 ), User("Dark", 23 ) ) for ((name, age) in p) { println("name: $name, age: $age") } }
坑6、解構宣告使用示例。
(1)函式返回一個數據類物件。
data class Result(val result: Int, val status: Status) fun function(……): Result { // 各種計算 return Result(result, status) } // 現在,使用該函式: val (result, status) = function(……)
(2)因為標準庫中對映具有entryset函式和component函式,所以可以直接遍歷一個對映(map),如果“value”不是用的資料類,記得重寫component函式和toString函式。
class User(var name: String = "", var age: Int = 0) { operator fun component1(): String { return name } operator fun component2(): Int { return age } override fun toString(): String { return "User(name='$name', age=$age)" } } fun main(args: Array<String>) { val map = HashMap<String, User>() map.put("1", User("Door", 22)) map.put("2", User("Green", 30)) map.put("3", User("Dark", 23)) map.put("4", User("Tool", 26)) map.put("5", User("Mark", 24)) for ((key, value) in map) { println("key: $key, value: $value") } }
坑7、下劃線不僅可以在lambda表示式中標記沒有用到的引數,也可以在解構宣告中標記未用到的變數。
坑8、在lambda表示式中解構。未使用的替換為下劃線,也可以為解構引數指定型別。
data class User(var name: String = "", var age: Int = 0) { } fun main(args: Array<String>) { val map = HashMap<String, User>() map.put("a", User("Door", 22)) map.put("b", User("Green", 30)) map.put("c", User("Dark", 23)) map.put("d", User("Tool", 26)) map.put("e", User("Mark", 24)) map.forEach { println(map.mapValues { entry -> "${entry.value} " }) println(map.mapValues { (_, v: User) -> "$v " }) } }
坑9、kotlin中的list集合是隻讀的,如果需要寫入,則使用MutableList。如果將MutableList型別物件賦值給List物件,則該List物件隨著MutableList物件的值的改變而改變。如果需要List只讀,則試用版listOf建立。
fun main(args: Array<String>) { val numbers: MutableList<Int> = mutableListOf(1, 2, 3) val readOnlyView: List<Int> = numbers println(numbers) // 輸出 "[1, 2, 3]" numbers.add(4) println(readOnlyView) // 輸出 "[1, 2, 3, 4]" }
坑10、你可以把一個 List<Rectangle> 賦值給 List<Shape> 假定 Rectangle 繼承自 Shape。對於可變集合型別這是不允許的,因為這將導致執行時故障。(沒懂。。。)
坑11、toList 擴充套件方法只是複製列表項,因此返回的 list 保證永遠不會改變
fun main(args: Array<String>) { private val _items = mutableListOf<String>() val i: List<String> = _items.toList() }
坑12、list、set、map常見的擴充套件方法。馬上下班了,就不一一驗證了。。。
fun main(args: Array<String>) { val items = listOf(1, 2, 3, 4) items.first() == 1 items.last() == 4 items.filter { it % 2 == 0 } // 返回 [2, 4] val rwList = mutableListOf(1, 2, 3) rwList.requireNoNulls() // 返回 [1, 2, 3] if (rwList.none { it > 6 }) println("No items above 6") // 輸出“No items above 6” val item = rwList.firstOrNull() //sort、zip、fold、reduce... val readWriteMap = hashMapOf("foo" to 1, "bar" to 2) println(readWriteMap["foo"]) // 輸出“1” val snapshot: Map<String, Int> = HashMap(readWriteMap) }
好了,我在android中遇到的list問題也成功解決,可變與不可變。
感謝閱讀,寫得太low,歡迎指正。