当前位置: 首页 > news >正文

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

这篇涉及到的知识点:  

扩展函数: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. 将配置好的对象赋值给 eventConfigeventConfig = newConfig

游戏类比

就像角色创建界面:

// 创建角色val character = Character()// 配置角色属性character.apply {name = "战士"level = 10weapon = "剑"armor = "铁甲"}// 使用配置好的角色player.character = character

等价的传统写法

传统方式
// 传统方式fun configureTraditional(): EventHandlerManager {val config = EventConfig()config.addValidator { rect -> rect != null }config.addHandler(EventType.CHAT) { rect ->handleChat(rect)}eventConfig = configreturn 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)}}}}

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

http://www.dtcms.com/a/288745.html

相关文章:

  • LINUX入门(二)QT的安装及运行环境搭建
  • jmeter如何做自动化接口测试?
  • 元宇宙经济的四个特征
  • Spring Boot中REST与gRPC并存架构设计与性能优化实践指南
  • Dify 1.6 安装与踩坑记录(Docker 方式)
  • LeetCode 198 打家劫舍 LeetCode 213.打家劫舍II
  • 华为开源自研AI框架昇思MindSpore应用案例:基于ERNIE模型实现对话情绪识别
  • [Python] -项目实战4- 利用Python进行Excel批量处理
  • 基于pyside6的通用机器人遥控控制界面
  • client-go: k8s选主
  • JAVA面试宝典 -《容灾设计:异地多活架构实践》
  • go-redis Pipeline 与事务
  • 民法学学习笔记(个人向) Part.1
  • 如何应对“躺平”文化对项目的冲击
  • 生物化学笔记:安全防护 射频和微波辐射防护 电磁辐射与防护 生物电磁学
  • 《镜语者》
  • 技术演进中的开发沉思-40 MFC系列:多线程协作
  • AI-Compass 前沿速览:ChatGPT Agent、Kimi2、Mistral 语音模型、Grok AI 情感陪伴、百度 Tizzy、有言数字人
  • java学习6--方法
  • 深入解析定点数移位运算:原理、规则与实例
  • Golang的微服务链路追踪
  • github 近期热门项目-2025.7.20
  • RabbitMQ面试精讲 Day 4:Queue属性与消息特性
  • 【图论】图的定义与一些常用术语
  • RabbitMQ:解锁高效消息传递的密码[特殊字符]
  • UE为什么FlipFlop按快了会触发Bug?
  • 【愚公系列】《MIoT.VC》002-构建基本仿真工作站(布局一个基本工作站)
  • springboot注册servlet
  • Qt 应用程序入口代码分析
  • 彩虹云商城全源码 - 全新客服系统上线