Delegated Properties 하시죠(슬라이드 버전)

16440 단어 Kotlin
며칠 후에 나는 기사를 잘 쓸 것이다.

오점


  • @kikuchy
  • 주식회사 Mixi->주식회사 Diverse
  • Android 쓰는 아저씨
  • 저는 지난번에 Kotlin에서 DSL을 했던 사람입니다.
    3분 Kotlin Friendly API

    Delegated Property란 무엇입니까?

  • 클래스 속성(구성원)의 setter/getter 처리를 다른 대상에 전달하는 기능
  • 특정한 방법만 실현되면 양도 대상이 된다
  • 뭐 공부 해요?


    지연 처리 가능!!!!!

    // Activityの中
    
    lateinit var hoge:String
    
    ...
    
    override fun onCreate(...) {
        // Fragment の arguments についても同様の悩みが
        hoge = intent.getStringExtra("hoge") ?: ""
    }
    
    구조 함수 때문에 초기화할 수 없습니다.val의 혜택을 받을 수 없습니다! lateinit만 사용 가능var

    보일러판을 대폭 줄일 수 있다!!!

    // Fragmentの中
    
    var listener: HogeFragmentActionListener? = null
    
    override onAttach(...) {
        if (activity is HogeFragmentActionListener) {
            listener = activity
        } else {
            throw Exception("""
      ActivityはHogeFragmentActionListenerを実装してないとだめ
            """)
        }
    }
    
    이거 일일이 Fragment에????

    다운그레이드된 속성을 사용하여 해결


    사용 방법 (1)

  • 실현에 필요한 방법
  • Extension에서도 설치할 수 있음
  • // 移譲元クラスが R、プロパティの型が T の場合
    
    operator fun getValue(
            thisRef: R, property: KProperty<*>): T
    
    // var 宣言したプロパティに使う場合は setValue も必要
    operator fun setValue(
            thisRef: R, property: KProperty<*>, value: T)
    

    사용 방법 (2)

  • by 키워드로 양도하는 실례 설정
  • class R {
        // HogeDelegate が getValueを実装しているとして
        val hoge: T by HogeDelegate()
    
        // FugaDelegate が getValue/setValueを実装しているとして
        var fuga: T by FugaDelegate()
    
    ...
    

    ✧\\ ٩( 'ω' )و //✧


    지금 바로 사용할 수 있는 예.


    표준 lazy


    속성을 처음 호출할 때 블록을 실행합니다.
    나중에 호출할 때 블록에서 되돌아오는 값을 사용합니다.
    val layoutManager: LinearLayoutManager by lazy {
        LinearLayoutManager(this)
    }
    

    표준 맵<K, V>

    Map<K, V>Extension이 있어 직접 양도지로 사용할 수 있습니다.
    class Hoge(val map: Map<String, String?>) {
    
        // map["fuga"] の値が返る
        val fuga: String? by map
    
    ...
    
    getValue 가운데MutableMap<K, V>도 있기 때문에 setValue의 양도 목적지가 될 수 있다.

    Kotter Knife


    Kotlin처럼 Butter Knife를 구현한 Jake 신삼제고.
    val userName: EditText by bindView(R.id.user_name)
    
    kt 파일의 단순성이기 때문에 Delegated Property를 배우기에 가장 적합하다.

    응용 프로그램


    Intent, Bundle에서 가져오기

    class IntentStringDelegate {
       operator fun getValue(
         thisRef: Activity, property: KProperty<*>): String?
           = thisRef.intent.getStringExtra(property.name)
    }
    
    ...
    
    val hoge: String? by IntentStringDelegate()
    
    ...
    
    // textView.text = intent.getString("hoge") 
    textView.text = hoge
    

    프레임 감청 프로그램 가져오기 (1)

    inline fun <reified T> listenerOfFragment(): ReadOnlyProperty<Fragment, T>
            = object : ReadOnlyProperty<Fragment, T> {
        private var value: T? = null
    
        override fun getValue(thisRef: Fragment, property: KProperty<*>): T {
            if (value == null)
                value = if (thisRef.parentFragment != null && thisRef.parentFragment is T) {
                    thisRef.parentFragment as T
                } else {
                    try {
                        thisRef.context as T
                    } catch (e: ClassCastException) {
                        throw ClassCastException("${thisRef.context.toString()} or parent Fragment must implement ${T::class.simpleName}")
                    }
                }
            @Suppress("UNCHECKED_CAST")
            return value as T
        }
    }
    

    프레임 감청 프로그램 가져오기 (2)

    private val loginListener: LoginListener
            by listenerOfFragment()
    
    ...
    
    loginListener.login(id, password)
    

    놀다


    신의 서명

    class OmikujiProperty{
        private val random = Random()
    
        operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
            return when(random.nextInt(4)) {
                0 -> "大吉"
                1 -> "中吉"
                2 -> "小吉"
                else -> "凶"
            }
        }
    }
    
    class Application {
        val omikuji: String by OmikujiProperty()
    
    }
    fun main(args: Array<String>) {
        val app = Application()
        print(app.omikuji)
    }
    
    kikuchy omikuji_kotlin $ ./gradlew :run
    (略)
    大吉
    BUILD SUCCESSFUL
    
    Total time: 6.161 secs
    
    kikuchy omikuji_kotlin $ ./gradlew :run
    (略)
    凶
    BUILD SUCCESSFUL
    
    Total time: 6.1 secs
    
    kikuchy omikuji_kotlin $ ./gradlew :run
    (略)
    凶
    BUILD SUCCESSFUL
    
    Total time: 5.993 secs
    
    kikuchy omikuji_kotlin $ ./gradlew :run
    (略)
    大吉
    BUILD SUCCESSFUL
    
    Total time: 5.988 secs
    
    kikuchy omikuji_kotlin $ ./gradlew :run
    (略)
    小吉
    BUILD SUCCESSFUL
    
    Total time: 5.955 secs
    

    Tips

  • 이전에 특정 인터페이스를 상속받은 대상이 양도 목적지가 됨
  • var
  • ReadOnlyProperty
  • ReadWriteProperty/getValue의 첫 번째 인수setValue의 유형을 지정하면 클래스의 속성만 지정할 수 있습니다.
  • 반대thisRef, 모든 종류의 속성에서 사용할 수 있다.
  • 질문?


    @kikuchy

    좋은 웹페이지 즐겨찾기