Kotlin의 튜토리얼을 시도한 ⑤

16583 단어 튜토리얼Kotlin
마지막으로 Swift 엔지니어는 Kotlin 튜토리얼을 계속 진행합니다. 이번은 Delegated properties 장입니다.
htps : // try. 이 tぃんぁ g. rg/#/에ぁmpぇs/로 ぇ가 d%20p로페 치에 s/쿠s와 m%20으로 ぇ가//s와 m%20으로 ぇ가. kt

자신이 구현한 만큼의 리포지토리



htps : // 기주 b. 코 m / 아카츠키 174 / 코 t ぃ
위의 DelegatedProperties.kt 파일

Delegated properties



Custom delegate


import kotlin.reflect.KProperty

class Example {
    var p: String by Delegate()

    override fun toString() = "Example Class"
}

class Delegate() {
    operator fun getValue(thisRef: Any?, prop: KProperty<*>): String {
        return "$thisRef, thank you for delegating '${prop.name}' to me!"
    }

    operator fun setValue(thisRef: Any?, prop: KProperty<*>, value: String) {
        println("$value has been assigned to ${prop.name} in $thisRef")
    }
}

fun main(args: Array<String>) {
    val e = Example()
    println(e.p) // getterが呼ばれる
    e.p = "NEW"  // setterが呼ばれる
}

프로퍼티의 뒤에 by 를 기술해 delegate 를 구현하고 있습니다. 속성의 delegates 는 interface 로 구현될 필요는 없습니다. 프로퍼티가 val 로 선언되고 있을 때는 getValue() 하지만, 프로퍼티이 var 로 선언되고 있을 때는 getValue() 에 가세해 setValue() 도 준비할 필요가 있습니다.

Lazy property


class LazySample {
    val lazy: String by lazy {
        println("computed!")
        "my lazy"
    }
}

fun main(args: Array<String>) {
    val sample = LazySample()
    // 1回目の呼び出し時にはクロージャ内の処理が行われるが
    // 2回目以降の呼び出し時には単に初回の評価結果が返される
    println("lazy = ${sample.lazy}")   // クロージャ内のprintln()文も実行される
    println("lazy = ${sample.lazy}")   // 初回評価結果である"my lazy"しかprintされない
}

이름대로 지연 속성을 나타냅니다. 처음에 get로 불렸을 때는 lazy()가 건네받은 람다 식이 실행되어 결과를 보관 유지합니다. 그 이후에 get로 불렸을 때는 그 보관 유지하고 있던 결과를 돌려줍니다.

디폴트의 ​​동작에서는 지연 프로퍼티의 평가는 동기되어 처리는 1 개의 thread, 참조는 모든 thread로부터 할 수 있는 상태가 됩니다. 초기화 대리자 동기화가 필요하지 않고 여러 스레드에서 동시에 실행할 수 있도록하려면 LazyThreadSafetyMode.PUBLICATION를 lazy() 함수의 매개 변수로 전달합니다. 만약 초기화가 항상 싱글 thread로 행해지는 것을 알고 있으면, LazyThreadSafetyMode.NONE 모드를 사용할 수 있습니다.

참고까지 이 enum의 공식 의 기술을 붙여 둡니다.


Observable property


import kotlin.properties.Delegates

class User {
    var name: String by Delegates.observable("no name") {
        d, old, new ->
        println(d) // -> var Person.name: kotlin.String
        println("$old - $new")
    }
}

fun main(args: Array<String>) {
    val user = User()
    println("最初 = ${person.name}")   // -> 最初 = no name
    person.name = "Carl"              // -> no name - Carl
    println("代入後 = ${person.name}") // -> 代入後 = Carl
}

observable 함수는 두 개의 인수(초기값과 수정을 위한 값(블록 부분))을 취합니다. 핸들러는 이름에 값을 할당할 때마다 호출되며 세 개의 매개변수(할당된 값, 이전 값, 새 값)가 있습니다.

observable() 대신 vetoable() 을 사용하면 속성에 할당하기 전에 람다 식이 실행되어 할당을 수행할지 여부를 값으로 반환합니다. 이렇게 하면 할당을 거부할 수 있습니다.
class Person {
    var age: Int by Delegates.vetoable(3) {
        d, old, new ->
        println("$old -> $new")
        old < new // 新しい値の方が大きくなかったら拒否
    }
}

val person = Person()
println("age: 最初 = ${person.age}")      // -> age: 最初 = 3
person.age = 4                           // -> 3 -> 4
println("age: 代入後 = ${person.age}")    // -> age: 代入後 = 4
person.age = 2                           // -> 4 -> 2
println("age: 代入拒否後 = ${person.age}") // -> age: 代入拒否後 = 4

NotNull property


import kotlin.properties.Delegates

class User {
    var name: String by Delegates.notNull()

    fun init(name: String) {
        this.name = name
    }
}

fun main(args: Array<String>) {
    val user = User()
    // user.name -> IllegalStateException
    user.init("Carl")
    println(user.name)
}

Kotlin에서는 초기화되지 않은 추상화되지 않은 속성을 가질 수 없습니다. null로 초기화할 수도 있지만 액세스할 때마다 확인해야 합니다. Kotlin에는 이것을 해결하는 delegate가 있으며 특정 속성에 쓰기 전에 읽기를 시도하면 예외가 발생합니다. 할당 후 예상대로 움직입니다.

Properties in map


class User(val map: Map<String, Any?>) {
    val name: String by map
    val age: Int     by map
}

fun main(args: Array<String>) {
    val user = User(mapOf(
            "name" to "John Doe",
            "age"  to 25
    ))

    println("name = ${user.name}, age = ${user.age}")
}

속성을 map에 저장하는 예입니다. Json을 퍼스하거나 다른 동적 일을 할 때 자주 사용됩니다. map에서 값을 꺼낼 때는 문자열의 키를 사용합니다.

물론, read-only의 map이 아닌 Mutable인 map으로 해 var를 사용하면 할당시에 map 변경을 가능하게 할 수 있습니다.
class Dog(val map: MutableMap<String, Any?>) {
    var name: String by map
    var age: Int     by map
}

val dog = Dog(mutableMapOf(
        "name" to "Pochi",
        "age" to 2
))

println("name = ${dog.name}, age = ${dog.age}")  // -> name = Pochi, age = 2

dog.name = "Taro"
dog.age = 3

println("name = ${dog.name}, age = ${dog.age}")  // -> name = Taro, age = 3

감상



notNull이 수수하게 편리하게 보입니다.



Swift에서도 초기화되지 않은 비 추상적 속성을 가질 수 없으며 값을 처음부터 할당 할 필요가 없다면 Int는 0이고 String은 ""로 초기화하거나 선택적으로 쓰고 있습니다. 하지 않고, notNull을 명시할 수 있는 것이 좋다고 생각했습니다.

업데이트가 쉽습니다.



IntelliJ IDEA의 이야기가 됩니다만 여러가지 업데이트가 편합니다. Kotlin의 버전 업, 플러그인 업데이트의 연락은 화면 오른쪽 하단에 나오고, 그것을 탭하면 해줍니다. Xcode보다 상당히 편하다고 생각했습니다.

좋은 웹페이지 즐겨찾기