Kotlin에서 'by'키워드는 무엇을합니까?


답변:


74

에서 코 틀린 참조 당신은 두 가지 용도를 찾을 수 있습니다 by, 첫 번째 인 위임 속성 은 위가 사용하는 것입니다 :

특정한 공통된 종류의 속성이 있는데, 우리가 필요할 때마다 수동으로 구현할 수 있지만 한 번에 구현하고 라이브러리에 넣는 것이 매우 좋습니다. 예를 들어 lazy 속성 : 값은 처음 액세스 할 때만 계산 됨, 관찰 가능한 속성 : 리스너는이 속성의 변경 사항에 대해 알림을 받고 속성을 각각 별도의 필드가 아닌 맵에 저장합니다.

여기서 작업을 수행하고 공통 코드를 포함 할 수있는 다른 클래스에 getter / setter를 위임합니다. 또 다른 예로, Kotlin의 일부 종속성 주입기는 종속성 주입 엔진이 관리하는 인스턴스의 레지스트리에서 값을 수신하도록 getter를 위임하여이 모델을 지원합니다.

그리고 인터페이스 / 클래스 위임 은 다른 용도입니다.

위임 패턴은 구현 상속에 대한 좋은 대안으로 입증되었으며 Kotlin은 기본적으로 상용구 코드가 필요하지 않도록 지원합니다. Derived 클래스는 Base 인터페이스에서 상속하고 모든 공용 메서드를 지정된 개체에 위임 할 수 있습니다.

여기에서 인터페이스를 다른 구현에 위임 할 수 있으므로 구현 클래스는 변경하려는 내용 만 재정의하면되고 나머지 메서드는 완전한 구현으로 다시 위임됩니다.

라이브 예제는 Klutter Readonly / Immutable 컬렉션 으로, 특정 컬렉션 인터페이스를 다른 클래스에 위임 한 다음 읽기 전용 구현에서 달라야하는 모든 것을 재정의합니다. 다른 모든 메서드를 수동으로 위임 할 필요없이 많은 작업을 절약 할 수 있습니다.

이 두 가지 모두 Kotlin 언어 참조 에서 다루고 있으며 언어의 기본 주제부터 시작합니다.


83

간단히 말해서에서 제공하는by 키워드를 이해할 수 있습니다 .

속성 소비자의 관점에서 보면 valgetter (get) var가 있고 getter와 setter (get, set)가있는 것입니다. 각 var속성에는 명시 적으로 지정할 필요가없는 get 및 set 메서드의 기본 공급자가 있습니다.

그러나 by키워드를 사용할 때이 getter / getter & setter가 다른 곳에서 제공된다는 것을 나타냅니다 (즉, 위임 됨). 그것은 것 제공 하여 뒤에 오는 기능 by.

따라서이 내장 get 및 set 메서드를 사용하는 대신 해당 작업을 명시 적 함수에 위임합니다.

매우 일반적인 예는 by lazy지연 로딩 속성입니다. 또한 Koin과 같은 종속성 주입 라이브러리를 사용하는 경우 다음과 같이 정의 된 많은 속성을 볼 수 있습니다.

var myRepository: MyRepository by inject()  //inject is a function from Koin

클래스 정의에서 동일한 원칙을 따르며 일부 기능이 제공되는 위치를 정의하지만 get 및 set뿐만 아니라 모든 메서드 / 속성 집합을 참조 할 수 있습니다.

class MyClass: SomeInterface by SomeImplementation, SomeOtherInterface

이 코드는 '저는 MyClass 클래스이고 SomeImplementation에서 제공하는 SomeInterface 인터페이스의 기능을 제공합니다. SomeOtherInterface를 직접 구현할 것입니다 (암시 적이므로 by거기에 없습니다 ). '


18

여기에 이미지 설명 입력

구문은 다음과 같습니다.

val/var <property name>: <Type> by <expression>. 

by 이후의 표현은 대리자입니다.

우리가 속성의 값에 액세스하려고하면 페이지를 우리가 호출하는 경우, 즉, () 얻을 속성의 방법 PgetValue () 의 방법을 위임 인스턴스가 호출됩니다.

우리가 속성의 값을 설정하려고하면 페이지를 우리가 호출하는 경우, 즉, ()를 설정 속성의 방법 의 setValue () 의 방법을 위임 인스턴스가 호출됩니다.


5

재산 위임 :

import kotlin.reflect.KProperty

class Delegate {
    // for get() method, ref - a reference to the object from 
    // which property is read. prop - property
    operator fun getValue(ref: Any?, prop: KProperty<*>) = "textA"
    // for set() method, 'v' stores the assigned value
    operator fun setValue(ref: Any?, prop: KProperty<*>, v: String) {
        println("value = $v")
    }
}

object SampleBy {
    var s: String by Delegate() // delegation for property
    @JvmStatic fun main(args: Array<String>) {
        println(s)
        s = "textB"
    }
}

결과:

textA
value = textB

수업 위임 :

interface BaseInterface {
    val value: String
    fun f()
}

class ClassA: BaseInterface {
    override val value = "property from ClassA"
    override fun f() { println("fun from ClassA") }
}

// The ClassB can implement the BaseInterface by delegating all public 
// members from the ClassA.
class ClassB(classA: BaseInterface): BaseInterface by classA {}

object SampleBy {
    @JvmStatic fun main(args: Array<String>) {
        val classB = ClassB(ClassA())
        println(classB.value)
        classB.f()
    }
}

결과:

property from ClassA
fun from ClassA

매개 변수 위임 :

// for val properties Map is used; for var MutableMap is used
class User(mapA: Map<String, Any?>, mapB: MutableMap<String, Any?>) {
    val name: String by mapA
    val age: Int by mapA
    var address: String by mapB
    var id: Long by mapB
}

object SampleBy {
    @JvmStatic fun main(args: Array<String>) {
        val user = User(mapOf("name" to "John", "age" to 30),
        mutableMapOf("address" to "city, street", "id" to 5000L))

        println("name: ${user.name}; age: ${user.age}; " +
        "address: ${user.address}; id: ${user.id}")
    }
}

결과:

name: John; age: 30; address: city, street; id: 5000
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.