2-2-9 快速掌握Kotlin-[]操作符

26 阅读4分钟

🌟 Kotlin的[]操作符:让对象像数组一样灵活使用!

嘿!看到你对Kotlin的[]操作符感兴趣,太棒了!这可是Kotlin中让代码更简洁、更优雅的"魔法"之一。别担心,我来帮你轻松掌握它!😄

🧩 什么是[]操作符?

在Kotlin中,[]操作符(索引操作符)允许我们像访问数组一样访问自定义对象。通过重载getset函数,我们可以实现类似数组的索引访问。

📌 基本原理

Kotlin的[]操作符是通过重载getset函数来实现的。这些函数需要使用operator关键字标记。

语法

// 重载get
operator fun get(index: Int): T

// 重载set
operator fun set(index: Int, value: T)

🌈 实际示例

1. 简单的列表类

class MyList<T>(vararg items: T) {
    private val list = items.toList()
    
    // 重载get,实现索引访问
    operator fun get(index: Int): T {
        return list[index]
    }
    
    // 重载set,实现修改元素
    operator fun set(index: Int, value: T) {
        // 实际应用中可能需要更复杂的逻辑
        // 这里简化了
        println("Setting element at $index to $value")
    }
}

fun main() {
    val list = MyList(1, 2, 3, 4)
    println(list[2]) // 输出: 3
    
    list[0] = 10 // 会调用set函数
    println(list[0]) // 输出: 10
}

2. 多维数组

class Matrix(private val data: Array<IntArray>) {
    // 重载二维索引
    operator fun get(row: Int, col: Int): Int {
        return data[row][col]
    }
    
    operator fun set(row: Int, col: Int, value: Int) {
        data[row][col] = value
    }
}

fun main() {
    val matrix = Matrix(arrayOf(intArrayOf(1, 2), intArrayOf(3, 4)))
    println(matrix[1, 0]) // 输出: 3
    
    matrix[0, 1] = 99 // 修改元素
    println(matrix[0, 1]) // 输出: 99
}

3. 字符串范围访问

class StringRange(val text: String) {
    operator fun get(start: Int, end: Int): String {
        return text.substring(start, end)
    }
}

fun main() {
    val text = StringRange("Hello, Kotlin!")
    println(text[0, 5]) // 输出: Hello
    println(text[7, 12]) // 输出: Kotlin
}

💡 为什么使用[]操作符?

  1. 代码更简洁:像数组一样直接访问,不需要调用get()方法
  2. 更直观:让代码更符合自然语言习惯
  3. 类型安全:Kotlin的编译器会确保类型安全
  4. 提高可读性:让代码意图更清晰

🌟 实际应用场景

1. 自定义集合类

class MyMap<K, V>(private val data: MutableMap<K, V>) {
    operator fun get(key: K): V? {
        return data[key]
    }
    
    operator fun set(key: K, value: V) {
        data[key] = value
    }
}

fun main() {
    val map = MyMap<String, Int>(mutableMapOf("one" to 1, "two" to 2))
    println(map["one"]) // 1
    map["three"] = 3
    println(map["three"]) // 3
}

2. 日期范围

class DateRange(val start: String, val end: String) {
    operator fun get(index: Int): String {
        // 简化示例,实际应用中可能需要更复杂的逻辑
        return if (index == 0) start else end
    }
}

fun main() {
    val range = DateRange("2023-01-01", "2023-12-31")
    println(range[0]) // 2023-01-01
    println(range[1]) // 2023-12-31
}

3. 数据库查询结果

class QueryResult(val rows: List<Map<String, Any>>) {
    operator fun get(index: Int): Map<String, Any> {
        return rows[index]
    }
    
    operator fun get(column: String): List<Any> {
        return rows.map { it[column] }
    }
}

fun main() {
    val result = QueryResult(listOf(
        mapOf("name" to "Alice", "age" to 30),
        mapOf("name" to "Bob", "age" to 25)
    ))
    
    println(result[0]["name"]) // Alice
    println(result["age"]) // [30, 25]
}

⚠️ 重要注意事项

  1. 必须使用operator关键字:没有operator关键字,编译器不会将函数识别为操作符重载
  2. 参数类型必须匹配getset的参数类型必须与访问时的类型一致
  3. 可以重载多个参数getset可以接受多个参数,实现多维索引
  4. 不要过度使用:过度使用可能降低代码可读性

💡 小贴士

  1. 命名约定getset是Kotlin中约定的函数名,不要使用其他名称
  2. 类型推断:Kotlin会自动推断类型,所以通常不需要显式指定
  3. 安全访问:使用?.操作符进行安全访问,避免IndexOutOfBoundsException
  4. 多维索引:通过多个参数实现多维索引,如get(row: Int, col: Int)

🌈 一个有趣的练习

试试看,写一个Page类,可以像访问数组一样访问页面的元素:

class Page(val content: List<String>) {
    operator fun get(index: Int): String {
        return content[index]
    }
    
    operator fun set(index: Int, value: String) {
        println("Updating page content at $index to $value")
    }
}

fun main() {
    val page = Page(listOf("Hello", "World", "Kotlin"))
    println(page[1]) // World
    page[0] = "Hi"
    println(page[0]) // Hi
}

📚 总结

操作符对应函数用途
a[i]get(i)获取元素
a[i] = valueset(i, value)设置元素

Kotlin的[]操作符是通过重载getset函数实现的,这使我们可以像使用数组一样访问自定义对象。这种设计让Kotlin的代码更简洁、更直观,是Kotlin语言中非常优雅的特性之一!