Kotlin Notes - 6

  1. To access this from an outer scope (a class, extension function, or labeled function literal with receiver) you write this@label, where @label is a label on the scope this is meant to be from:

    class A { // implicit label @A
        inner class B { // implicit label @B
            fun Int.foo() { // implicit label @foo
                val a = this@A // A's this
                val b = this@B // B's this
    
                val c = this // foo()'s receiver, an Int
                val c1 = this@foo // foo()'s receiver, an Int
    
                val funLit = lambda@ fun String.() {
                    val d = this // funLit's receiver, a String
                }
    
                val funLit2 = { s: String ->
                    // foo()'s receiver, since enclosing lambda expression
                    // doesn't have any receiver
                    val d1 = this
                }
            }
        }
    }
    
  2. Destructuring declarations

    val (name, age) = person
    
    for ((a, b) in collection) { ... }
    
    for ((key, value) in map) {
       // do something with the key and the value
    }
    
    val (_, status) = getResult()
    
    map.mapValues { entry -> "${entry.value}!" }
    map.mapValues { (key, value) -> "$value!" }
    
  3. let: The Kotlin standard library function let can be used for scoping and null-checks. When called on an object, let executes the given block of code and returns the result of its last expression. The object is accessible inside the block by the reference it (by default) or a custom name.

    val empty = "test".let {               // 1
        customPrint(it)                    // 2
        it.isEmpty()                       // 3
    }
    println(" is empty: $empty")
    
    
    fun printNonNull(str: String?) {
        println("Printing \"$str\":")
    
        str?.let {                         // 4
            print("\t")
            customPrint(it)
            println()
        }
    }
    
    fun printIfBothNonNull(strOne: String?, strTwo: String?) {
        strOne?.let { firstString ->       // 5 
            strTwo?.let { secondString ->
                customPrint("$firstString : $secondString")
                println()
            }
        }
    }
    
    printNonNull(null)
    printNonNull("my string") 
    printIfBothNonNull("First","Second") 
    
  4. run:Like let, run is another scoping function from the standard library. Basically, it does the same: executes a code block and returns its result. The difference is that inside run the object is accessed by this. This is useful when you want to call the object's methods rather than pass it as an argument.

    fun getNullableLength(ns: String?) {
        println("for \"$ns\":")
        ns?.run {                                                  // 1
            println("\tis empty? " + isEmpty())                    // 2
            println("\tlength = $length")                           
            length                                                 // 3
        }
    }
    getNullableLength(null)
    getNullableLength("")
    getNullableLength("some string with Kotlin")
    
  5. with: with is a non-extension function that can access members of its argument concisely: you can omit the instance name when referring to its members.

    with(configuration) {
        println("$host:$port")
    }
    
    // instead of:
    println("${configuration.host}:${configuration.port}")    
    
  6. apply: apply executes a block of code on an object and returns the object itself. Inside the block, the object is referenced by this. This function is handy for initializing objects.

    val jake = Person()                                     // 1
    val stringDescription = jake.apply {                    // 2
        name = "Jake"                                       // 3
        age = 30
        about = "Android developer"
    }.toString()             
    
  7. also: also works like apply: it executes a given block and returns the object called. Inside the block, the object is referenced by it, so it's easier to pass it as an argument. This function is handy for embedding additional actions, such as logging in call chains.

    val jake = Person("Jake", 30, "Android developer")   // 1
        .also {                                          // 2 
            writeCreationLog(it)                         // 3
        }
    
posted @ 2023-12-04 23:08  Otlpy  阅读(18)  评论(0)    收藏  举报