kotlin 扩展函数 在链式调用的妙用

发布于:2025-07-21 ⋅ 阅读:(15) ⋅ 点赞:(0)

这篇涉及到的知识点:  

扩展函数:Kotlin 扩展函数详解_kotlin扩展函数-CSDN博客

设计模式: builder 模式 :建造者模式(Builder)-CSDN博客

高阶函数 :Kotlin --- 函数,高阶函数_kotlin 高阶函数-CSDN博客

 高阶函数,父子组件:  Compose 父子组件的通信_jetpack compose 子组件数据传递-CSDN博客

详细解释这个 configure 方法的语法和工作原理:

configure 方法解析

语法分解

fun configure(init: EventConfig.() -> Unit): EventHandlerManager {

    eventConfig = EventConfig().apply(init)

    return this

}

各部分含义

init: EventConfig.() -> Unit

  • init 是参数名
  • EventConfig.() 是带接收者的函数类型
  • -> Unit 表示函数返回 Unit(无返回值)

EventConfig.() 是什么?

  • 这是 Kotlin 的扩展函数语法
  • 表示这个函数在 EventConfig 对象内部执行
  • 函数内部可以直接访问 EventConfig 的属性和方法

EventConfig().apply(init)

  • EventConfig() 创建新对象
  • .apply(init) 在新对象上执行 init 函数

apply { }  和apply()  区别?

真正的区别是:

  • apply { } 是直接写代码块
  • apply(init) 是通过函数参数传入代码块

但执行时机是相同的,都是立即执行。

实际使用示例

调用方式

// 调用方式

eventHandlerManager.configure {

    // 这里的 this 就是 EventConfig 对象

    addValidator { rect -> rect != null }

    addHandler(EventType.CHAT) { rect ->

        handleChat(rect)

    }

}

执行过程

// 1. 创建新的 EventConfig 对象

val newConfig = EventConfig()

// 2. 在 newConfig 上执行配置函数

newConfig.apply {

    addValidator { rect -> rect != null }

    addHandler(EventType.CHAT) { rect ->

        handleChat(rect)

    }

}

// 3. 将配置好的对象赋值给 eventConfig

eventConfig = newConfig

游戏类比

就像角色创建界面:

// 创建角色

val character = Character()

// 配置角色属性

character.apply {

    name = "战士"

    level = 10

    weapon = "剑"

    armor = "铁甲"

}

// 使用配置好的角色

player.character = character

等价的传统写法

传统方式
// 传统方式

fun configureTraditional(): EventHandlerManager {

    val config = EventConfig()

    config.addValidator { rect -> rect != null }

    config.addHandler(EventType.CHAT) { rect ->

        handleChat(rect)

    }

    eventConfig = config

    return this

}
扩展函数方式
// 使用扩展函数的方式(当前实现)

fun configure(init: EventConfig.() -> Unit): EventHandlerManager {

    eventConfig = EventConfig().apply(init)

    return this

}

调用对比

// 传统方式调用

eventHandlerManager.configureTraditional()

// 扩展函数方式调用(更优雅)

eventHandlerManager.configure {

    addValidator { rect -> rect != null }

    addHandler(EventType.CHAT) { rect ->

        handleChat(rect)

    }

}

为什么这样设计?

  1. 链式调用:return this 支持链式调用
  2. 代码块:{} 提供配置代码块
  3. 作用域:在 EventConfig 作用域内执行
  4. 简洁性:比传统方式更简洁

完整示例

// 配置事件处理器

eventHandlerManager

    .configure {

        // 添加验证器

        addValidator { rect -> rect != null }

        addValidator { rect -> rect.text.isNotEmpty() }

        

        // 添加事件处理器

        addHandler(EventType.CHAT) { rect ->

            Log.d("Chat", "处理聊天事件: ${rect.text}")

        }

        

        addHandler(EventType.PDF) { rect ->

            Log.d("PDF", "处理PDF事件: ${rect.text}")

        }

    }

    .registerAllHandlers()  // 链式调用
    /**
     * 注册所有事件处理器
     * 根据配置注册相应的事件处理器
     */
    fun registerAllHandlers() {
        eventConfig.handlers.forEach { (type, handler) ->
            registerHandler(type, handler)
        }
        Log.d(TAG, "所有事件处理器注册完成")
    }
    /**
     * 注册单个事件处理器
     * @param type 事件类型
     * @param handler 处理函数
     */
    private fun registerHandler(type: EventType, handler: (ColoredRect) -> Unit) {
        when (type) {
            EventType.CHAT -> deepLearnView.registerButtonClickHandler(RectType.START_CHAT) { rect ->
                if (validateRect(rect)) {
                    handler(rect)
                }
            }
            EventType.QUESTION -> deepLearnView.registerQuestionConfirmButtonClickHandler { rect ->
                if (validateRect(rect)) {
                    handler(rect)
                }
            }
            EventType.QUESTION_BUTTON -> deepLearnView.registerQuestionButtonClickHandler(0) { rect, buttonIndex, buttonText ->
                if (validateRect(rect)) {
                    // 这里需要特殊处理,因为问答按钮处理器有额外参数
                    // 可以扩展 EventConfig 来支持带参数的处理函数
                    handler(rect)
                }
            }
            EventType.OCR -> deepLearnView.registerOcrButtonClickHandler { rect ->
                if (validateRect(rect)) {
                    handler(rect)
                }
            }
            EventType.OCR_ADD_IMAGE -> deepLearnView.registerOcrAddImageClickHandler { rect ->
                if (validateRect(rect)) {
                    handler(rect)
                }
            }
            EventType.PDF -> deepLearnView.registerButtonClickHandler(RectType.PDF) { rect ->
                if (validateRect(rect)) {
                    handler(rect)
                }
            }
            EventType.SEARCH -> deepLearnView.registerButtonClickHandler(RectType.SEARCH) { rect ->
                if (validateRect(rect)) {
                    handler(rect)
                }
            }
        }
    }

这样设计让配置代码更加优雅和直观,就像在配置一个对象一样!


网站公告

今日签到

点亮在社区的每一天
去签到