[runoob.15] 의뢰 모드???

4961 단어

클래스 위임


클래스의 의뢰는 하나의 클래스에서 정의된 방법으로 실제적으로 다른 클래스의 대상을 호출하는 방법으로 이루어진다.다음 예에서 파생 클래스 Derived는 인터페이스 Base의 모든 방법을 계승하고, 이 방법을 실행하기 위해 전송된 Base 클래스의 대상을 의뢰합니다.
//  
interface Base {   
    fun print()
}

//  
class BaseImpl(val x: Int) : Base {
    override fun print() { print(x) }
}

//   by  
class Derived(b: Base) : Base by b

fun main(args: Array) {
    val b = BaseImpl(10)
    Derived(b).print() //   10
}

의뢰된 클래스 정의


이 클래스는 getValue () 방법과 setValue () 방법을 포함하고, 매개 변수thisRef는 의뢰를 진행하는 클래스의 대상이며, prop는 의뢰를 진행하는 속성의 대상이다.
import kotlin.reflect.KProperty
//  
class Example {
    var p: String by Delegate()
}

//  
class Delegate {
    operator fun getValue(thisRef: Any?, property: KProperty): String {
        return "$thisRef,   ${property.name}  "
    }

    operator fun setValue(thisRef: Any?, property: KProperty, value: String) {
        println("$thisRef   ${property.name}   $value")
    }
}
fun main(args: Array) {
    val e = Example()
    println(e.p)     //  ,  getValue()  

    e.p = "Runoob"   //   setValue()  
    println(e.p)
}

출력 결과는 다음과 같습니다.
Example@433c675d,   p  
Example@433c675d   p   Runoob
Example@433c675d,   p  

지연 속성 레이지(???)

lazy()는 함수로 Lambda 표현식을 매개 변수로 받아들여 Lazy 실례의 함수를 되돌려주고 되돌려주는 실례는 지연 속성을 실현하는 의뢰로 할 수 있다. 첫 번째 호출get()lazy()에 전달된 Lamda 표현식을 실행하고 결과를 기록하며 후속 호출get()은 기록된 결과만 되돌려준다.
val lazyValue: String by lazy {
    println("computed!")     //  , 
    "Hello"
}

fun main(args: Array) {
    println(lazyValue)   //  , 
    println(lazyValue)   //  , 
}

출력 수행 결과:
computed!
Hello
Hello

관찰가능 속성 Observable


observable는 관찰자 모드를 실현하는 데 사용할 수 있습니다.Delegates.observable () 함수는 두 개의 인자를 받아들인다. 첫 번째는 초기화 값이고, 두 번째는 속성 값 변화 이벤트의 응답기 (handler) 이다.속성에 값을 부여한 후에 이벤트를 실행하는 응답기(handler)는 세 가지 인자가 있습니다. 그것이 바로 값을 부여받은 속성, 옛 값과 새 값입니다.
import kotlin.properties.Delegates

class User {
    var name: Int by Delegates.observable(0) {
        prop, old, new -> Log.d(JTAG, "$old -> $new")
    }

    var gender: Int by Delegates.vetoable(0) {
        prop, old, new -> (old < new)
    }
}

fun test(){
    val user = User()
    user.name = 2    //   0 -> 2        
    user.name = 1   //   2 -> 1    

    user.gender = 2
    Log.d(JTAG, user.gender.string())   //   2
    user.gender = 1
    Log.d(JTAG, user.gender.string())   //   2
}

observable는 set 변화를 실행한 후에야 observable를 터치합니다.vetoable는 set이 실행되기 전에 터치되며, Boolean을 되돌려줍니다.true가 되어야만 set을 계속 실행할 수 있습니다.위의 예에서, 우리는 첫 번째 값을 부여한 사용자를 보았다.gender = 2시, 2>0이므로old

위탁 제공(???)


provideDelegate 조작부호를 정의함으로써 위탁 대상의 논리를 실현하는 속성을 확장할 수 있습니다.만약by 오른쪽에 있는 대상이provideDelegate를 구성원이나 확장 함수로 정의한다면, 이 함수를 호출하여 속성 의뢰 실례를 만들 것입니다.provideDelegate의 가능한 사용 장면은 속성을 만들 때 (Getter나setter뿐만 아니라) 속성 일치성을 검사하는 것입니다.예를 들어, 바인딩하기 전에 속성 이름을 확인하려면 다음과 같이 하십시오.
class ResourceLoader(id: ResourceID) {
    operator fun provideDelegate(
            thisRef: MyUI,
            prop: KProperty
    ): ReadOnlyProperty {
        checkProperty(thisRef, prop.name)
        //  
    }

    private fun checkProperty(thisRef: MyUI, name: String) { …… }
}

fun  bindResource(id: ResourceID): ResourceLoader { …… }

class MyUI {
    val image by bindResource(ResourceID.image_id)
    val text by bindResource(ResourceID.text_id)
}

provideDelegate의 매개 변수는 getValue와 같습니다:thisRef - 속성 소유자 형식 (확장된 속성에 대해 - 확장된 유형을 가리키는 것) 과 같거나, 초형식property에 대해 Kproperty 형식이나 초형식이어야 합니다.MyUI 실례를 만드는 동안 모든 속성에provideDelegate 방법을 호출하고 필요한 검증을 즉시 실행합니다.만약 이러한 속성과 의뢰 사이의 연결을 차단하는 능력이 없다면, 같은 기능을 실현하기 위해서는 속성 이름을 현시적으로 전달해야 합니다. 이것은 매우 편리하지 않습니다://속성 이름을 검사하고 "provide Delegate"기능을 사용하지 마십시오.
class MyUI {
    val image by bindResource(ResourceID.image_id, "image")
    val text by bindResource(ResourceID.text_id, "text")
}

fun  MyUI.bindResource(
        id: ResourceID,
        propertyName: String
): ReadOnlyProperty {
   checkProperty(this, propertyName)
   //  
}

생성된 코드에서provideDelegate 방법을 호출하여 보조적인prop$delegate 속성을 초기화합니다.속성 선언 val prop: Type by My Delegate()에서 생성된 코드와 위쪽(provide Delegate 메서드가 존재하지 않을 때) 생성된 코드를 비교합니다.
class C {
    var prop: Type by MyDelegate()
}

//  “provideDelegate” 
//  :
class C {
    //  “provideDelegate” “delegate” 
    private val prop$delegate = MyDelegate().provideDelegate(this, this::prop)
    val prop: Type
        get() = prop$delegate.getValue(this, this::prop)
}

provideDelegate 방법은 보조 속성의 생성에만 영향을 주고 Getter나setter에 생성된 코드에는 영향을 주지 않습니다.

좋은 웹페이지 즐겨찾기