002-Kotlin界面开发之Kotlin旋风之旅
Kotlin旋风之旅
Compose Desktop中哪些Kotlin知识是必须的?
在学习Compose Desktop中,以下Kotlin知识是必须的:
- 基础语法:包括变量声明、数据类型、条件语句、循环等。
- 面向对象编程:类与对象、继承、接口、抽象类等。
- 函数式编程:高阶函数、Lambda表达式、内联函数等。
- 协程:理解协程的基本概念、使用launch和async等构建并发程序。
- Kotlin标准库:熟悉常用的集合操作、字符串处理、文件I/O等。
- DSL(领域特定语言):Compose本身就是一个DSL,理解如何构建和使用DSL非常重要。
- Kotlin扩展函数:如何为现有类添加新功能。
- Kotlin特性:如空安全、数据类、解构声明等。
- 掌握这些知识将有助于你更好地使用Compose Desktop进行开发。
基础语法
变量与类型
在Kotlin中,使用val
和var
关键字来声明变量。val
声明的变量是只读的,一旦赋值就不能再修改;var
声明的变量是可变的。
从下面的例子可以看到,1)变量类型后置;2)没有分号!
val name: String = "Alice"
val age: Int = 18
val isStudent: Boolean = true
var score: Double = 99.5
并且,Kotlin中的变量类型可以省略,编译器会根据赋值的类型自动推断变量的类型。
val name: String = "Alice"
val age: Int = 18
val isStudent: Boolean = true
var score: Double = 99.5
在Java的基础上,Kotlin引入了一些新的数据类型,如String
、Int
、Boolean
等。这些数据类型是不可变的,也就是说,一旦创建,就不能再修改。总的来说,Kotlin的基础数据类型某些时候比Java的更好用,提供了更多的功能。Kotlin的类与Java的类可以直接互操作,这是因为Kotlin是在Java虚拟机上运行的。
通过变量的javaClass
属性,可以获取变量的Java类。
val name: String = "Alice"
println("name is a Java Class: ${name.javaClass}") // class java.lang.String
这里还可以看到,Kotlin的字符串是Java的String
类,同时,Kotlin支持字符串模板,可以在字符串中插入变量。
对于变量和类型,Kotlin最甜的就是增加了扩展方法,这是Java中没有的特性。扩展方法可以为现有的类添加新的方法,而不需要继承这个类。这样,我们可以为Java的类添加新的方法,而不需要修改Java的源代码。
fun String.addHello(): String {return "Hello, $this"
}val name: String = "Alice"
println(name.addHello()) // Hello, Alice
Kotlin标准库和基础类型中有很多这样的扩展方法,可以方便地操作字符串、集合等。同时,也可以定义扩展属性,因为属性本身就只是两个方法的语法糖(Java就没有~~~)。
扩展方法在Jetpack Compose中非常常见,非常常用。🙋♀️🌰,描述尺寸时,常常会使用一个单位Dp
,那么调用的时候通常会有
val size: Dp = 16.dp
后面这个语法就特别奇怪,居然调用整数的dp
属性,简直翻天了。在源程序中,我们可以看到:
@Stable
inline val Int.dp: Dp get() = Dp(value = this.toFloat())
这是一个只读的属性(只有get
方法),返回的是一个Dp
对象。这个Dp
对象是一个数据类,包含一个value
属性,表示尺寸的值。这样,我们就可以直接使用Int
的dp
属性来创建一个Dp
对象,而不需要调用Dp
的构造函数。真是完美的语法糖。
控制语句
在Java的基础上,Kotlin引入了一些新的控制语句,如when
表达式、if
表达式等。这些新的控制语句使得代码更加简洁、易读。
when
表达式是Kotlin中的一个强大的控制语句,可以替代Java中的switch
语句。when
表达式可以匹配任意类型的值,可以是常量、变量、表达式等。
val score = 90
val rank = when (score) {in 90..100 -> "优秀"in 80..89 -> "良好"in 70..79 -> "中等"in 60..69 -> "及格"else -> "不及格"
}
这里也看到,when
是一个表达式,可以直接赋值给一个变量。
同样,if
也是一个表达式,可以直接赋值给一个变量。
val score = 90
val result = if (score >= 60) "及格" else "不及格"
在循环方面,Kotlin也引入了一些新的语法,如for
循环、while
循环等。for
循环可以遍历任何实现了Iterable
接口的对象,如数组、集合等。
val names = listOf("Alice", "Bob", "Charlie")
for (name in names) {println(name)
}
这些都不重要,看到能够理解应该就够了。
面向对象编程
Kotlin首先是完全继承了Java的面向对象特性的,所以,Kotlin中的类、对象、接口、继承、多态等概念都和Java中的一样。但是,Kotlin中也引入了一些新的特性,如数据类、枚举类、对象类等。
数据类
数据类是Kotlin中的一个特殊类,用于存储数据。数据类会自动生成equals()
、hashCode()
、toString()
等方法,使得数据类更加易于使用。
data class User(val name: String, val age: Int)
这里定义了一个数据类User
,包含两个属性name
和age
。这样,我们就可以直接创建一个User
对象,而不需要手动实现equals()
、hashCode()
等方法。
val user1 = User("Alice", 18)
val user2 = User("Alice", 18)
println(user1 == user2) // true
能用则用,简直太香了。
枚举类
枚举类是Kotlin中的一个特殊类,用于表示一组常量。枚举类可以包含多个枚举常量,每个枚举常量都有一个名称和一个值。
enum class Color {RED, GREEN, BLUE
}
这里定义了一个枚举类Color
,包含三个枚举常量RED
、GREEN
、BLUE
。这样,我们就可以直接使用枚举常量,而不需要手动定义常量。
val color = Color.RED
这个也比Java的香太多, 转换到数字,转换到字符串,都是一行代码的事情。
对象类
在Java中,单例有的时候是一个很重要的设计模式。Kotlin直接增加了一个object
关键字,用于定义单例对象。
object Singleton {fun sayHello() {println("Hello, Singleton!")}
}
这里定义了一个单例对象Singleton
,包含一个sayHello()
方法。这样,我们就可以直接使用单例对象,而不需要手动实现单例模式。
Singleton.sayHello()
这个也是非常香的,不需要写那么多的代码,直接就是一个单例对象。
函数式编程
Java是一个面向对象的编程语言,而Kotlin是一个面向对象和函数式编程的编程语言。Kotlin中的函数是一等公民,可以作为参数、返回值、变量等使用。
高阶函数
高阶函数是Kotlin中的一个重要概念,指的是可以接受函数作为参数、返回函数的函数。高阶函数可以使代码更加简洁、易读。
fun add(a: Int, b: Int): Int {return a + b
}fun subtract(a: Int, b: Int): Int {return a - b
}fun calculate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {return operation(a, b)
}
这里定义了两个函数add()
和subtract()
,分别用于加法和减法。然后定义了一个高阶函数calculate()
,用于计算两个数的和或差。
val sum = calculate(1, 2, ::add)
val difference = calculate(1, 2, ::subtract)
这里全局函数add
和subtract
都是函数类型(Int, Int) -> Int
,所以可以直接传递给calculate
函数。并且::
是函数引用操作符,可以获取函数的引用。实际上,Kotlin利用了Java的静态类的静态方法的特性,将函数作为一个静态方法传递给了calculate
函数。
Lambda表达式
对于上面那个例子,我们还可以用一些更加魔幻的调用方式:
val chaos = calculate(1, 2, { a, b -> a*b + a / b })
这里,{ a, b -> a*b + a / b }
就是一个Lambda表达式,用于计算两个数的乘积加上商。Lambda表达式是一种匿名函数,可以作为参数传递给函数。Lambda表达式的语法是{ 参数列表 -> 函数体 }
,参数列表和函数体之间用->
分隔。
进一步,Kotlin提供了一个极其变态的语法糖,上面的调用可以写成:
val chaos = calculate(1, 2) { a, b -> a*b + a / b }
这看起来就像是一个方法定义,但是实际上是一个方法调用。这个语法糖是Kotlin中的一个特性,使得代码更加简洁、易读(并不是~~~)
引用对象的函数
全局的方法,我们用::
来引用,那么对于对象的方法,我们可以直接引用:
class Calculator {fun add(a: Int, b: Int): Int {return a + b}
}val calculator = Calculator()
val sum = calculator::add
这里,calculator::add
就是引用calculator
对象的add
方法。这样,我们就可以直接使用sum
变量来调用add
方法。
val result = sum(1, 2)
运算符重载
这个是Kotlin的一个特性,可以为现有的类添加新的运算符。运算符重载可以使代码更加简洁、易读。
这里我们就介绍一个重载,就是把一个类伪装成一个函数。
data class Point(val x: Int, val y: Int) {operator fun invoke(): String {return "($x, $y)"}
}
这里定义了一个数据类Point
,包含两个属性x
和y
。然后重载了invoke
运算符,使得Point
类可以像函数一样调用。
val point = Point(1, 2)
println(point()) // (1, 2)
DSL之假装调用奇怪的东西
当我们把重载调用操作符和Lambda表达式结合起来,就可以创建一种奇怪的东西:
class Calculation {var result: Int = 0operator fun plusAssign(value: Int) {result += value}
}class CalculationScope {operator fun invoke(block: Calculation.() -> Unit): Calculation {val calculation = Calculation()calculation.block()return calculation}
}
这里定义了一个Calculation
类,包含一个result
属性和一个plusAssign
运算符重载。然后定义了一个CalculationScope
类,包含一个invoke
运算符重载。
这个方法调用的是Calculation
的一个扩展函数,这个扩展函数是一个Lambda表达式,这个Lambda表达式的接收者是Calculation
对象。这样,我们就可以使用CalculationScope
类创建一个Calculation
对象,并使用plusAssign
运算符重载。
val cs = CalculationScope()
val calculation = cs() {result += 1result += 2result.plusAssign(3)
}println(calculation.result) // 6
首先,我们创建了一个CalculationScope
对象cs
,然后使用cs
对象创建了一个Calculation
对象calculation
。
在calculation
的扩展函数(block
)中,我们使用了plusAssign
函数,直接操作了result
。这简直是三观丧尽、斯文扫地……我们程序员都看不懂了。
这个玩意是Kotlin实现各种奇葩DSL的基础:
- 扩展函数
- 运算符重载
- Lambda表达式
- 接收者类型
Jetpack Compose的DSL
Jetpack Compose是一个基于Kotlin的DSL(领域特定语言),用于构建用户界面。DSL是一种专门用于某个领域的编程语言,用于简化特定领域的编程任务。
Jetpack Compose的DSL是基于函数式编程的,使用函数来构建用户界面。这种DSL的设计使得Jetpack Compose非常灵活、易用。
这里就详细介绍了,后面会在恰当的时候再介绍。
总结
其他需要掌握的知识,如协程、Kotlin标准库、Kotlin特性等,都是Kotlin的高级特性,对于Compose Desktop的开发这个学习阶段并不是必须的。
相关文章:

002-Kotlin界面开发之Kotlin旋风之旅
Kotlin旋风之旅 Compose Desktop中哪些Kotlin知识是必须的? 在学习Compose Desktop中,以下Kotlin知识是必须的: 基础语法:包括变量声明、数据类型、条件语句、循环等。面向对象编程:类与对象、继承、接口、抽象类等。…...

VMware Workstation Pro for Personal Use (For Windows)
这是从broadcom.com网下载的个人版本的Vmware 17.6.1,存分享不要分。 VMware-workstation-full-17.6.1-24319023.exe(447.93 MB) Build Number: 24319023 Oct 08, 2024 07.33AM SHA2: f95429e395a583eb5ba91f09b040e2f8c53a5e7aa37c4c6bfcaf82115a8…...

论文 | PROMPTAGATOR : FEW-SHOT DENSE RETRIEVAL FROM 8 EXAMPLES
1. 背景信息 在信息检索领域,传统的方法往往依赖于大量的标注数据来训练模型,以便在各种任务中表现良好。然而,许多实际应用中的监督数据是有限的,尤其是在不同的检索任务中。最近的研究开始关注如何从一个拥有丰富监督数据的任务…...

使用 Github 进行项目管理
GitHub 是一个广泛使用的代码托管和协作平台,它提供了强大的工具来支持项目管理和团队协作。在项目开发和工作中,避免不了 Github 的使用,然鹅我一直没有稍微系统地学习过 github 的整个工作流程,对这些操作都是一知半解的&#x…...
企业SRC挖掘选择与信息收集指南
内容预览 ≧∀≦ゞ 企业SRC挖掘选择与信息收集指南导语1. 企业SRC的选择2. 信息收集2.1 集团与子公司2.2 小程序与APP2.3 Web端信息收集 3. 信息收集常用模板总结 企业SRC挖掘选择与信息收集指南 导语 近年来,企业的安全响应中心(SRC)已逐渐…...

Golang | Leetcode Golang题解之第524题通过删除字母匹配到字典里最长单词
题目: 题解: func findLongestWord(s string, dictionary []string) (ans string) {m : len(s)f : make([][26]int, m1)for i : range f[m] {f[m][i] m}for i : m - 1; i > 0; i-- {f[i] f[i1]f[i][s[i]-a] i}outer:for _, t : range dictionary …...

【DBeaver】连接带kerberos的hive[Apache|HDP]
目录 一、安装配置Kerberos客户端环境 1.1 安装Kerberos客户端 1.2 环境配置 二、基于Cloudera驱动创建连接 三、基于Hive原生驱动创建连接 一、安装配置Kerberos客户端环境 1.1 安装Kerberos客户端 在Kerberos官网下载,地址如下:https://web.mit.edu/kerberos…...

Unity3D 开发教程:从入门到精通
Unity3D 开发教程:从入门到精通 Unity3D 是一款强大的跨平台游戏引擎,广泛应用于游戏开发、虚拟现实、增强现实等领域。本文将详细介绍 Unity3D 的基本概念、开发流程以及一些高级技巧,帮助你从零基础到掌握 Unity3D 开发。 目录 Unity3D…...

文件操作和 IO(一):文件基础知识 文件系统操作 => File类
目录 1. 什么是文件 1.1 概念 1.2 硬盘, 内存, 寄存器之间的区别 1.3 机械硬盘和固态硬盘 2. 文件路径 2.1 绝对路径 2.2 相对路径 3. 文件分类 4. File 类 4.1 属性 4.2 构造方法 4.3 方法 1. 什么是文件 1.1 概念 狭义上的文件: 保存在硬盘上的文件广义的上的文…...

用Pyhon写一款简单的益智类小游戏——2048
文字版——代码及讲解 代码—— import random# 初始化游戏棋盘 def init_board():return [[0] * 4 for _ in range(4)]# 在棋盘上随机生成一个2或4 def add_new_tile(board):empty_cells [(i, j) for i in range(4) for j in range(4) if board[i][j] 0]if empty_cells:i,…...

akshare股票涨跌幅自定义范围查询:A股、港股、美股
参看:https://stock.hexun.com/2024-10-31/215251914.html 涨幅计算公式:(当前价格 - 上一个交易日收盘价) 上一个交易日收盘价 100% 。 跌幅计算公式:(上一个交易日收盘价 - 当前价格) 上一个…...
通过js控制修改css变量
在JavaScript中,你可以通过操作CSS变量(也称为自定义属性)来动态改变样式。CSS变量在CSS中使用 – 前缀定义,例如 --main-color: red;。在JavaScript中,你可以使用 document.documentElement.style.setProperty 方法来…...

<HarmonyOS第一课>HarmonyOS SDK开放能力简介的课后习题
不出户,知天下; 不窥牖,见天道。 其出弥远,其知弥少。 是以圣人不行而知,不见而明,不为而成。 本篇<HarmonyOS第一课>HarmonyOS SDK开放能力简介是简单介绍了HarmonyOS SDK,不需要大家过多…...
深度学习:yolo的使用--图像处理
定义了一个名为 ListDataset 的类,它继承自 PyTorch 的 Dataset 类,这个数据集从一个包含图像文件路径的列表中读取图像和对应的标签文件 class ListDataset(Dataset):def __init__(self, list_path, img_size416, augmentTrue, multiscaleTrue, normalized_labelsT…...
TypeScript实用笔记(一):初始化、类型定义与函数使用
文章目录 一、ts初始化1. 初始化.json文件一2. 启动方式2.1 直接运行.ts文件2.2 转换运行 二、类型1. 参数类型1.1 常规参数1.2 symbol1.3 数组\[]1.4 元组\[]1.5 用字面量定义数据类型 2. Object3. 枚举类型\[Enum]3.1 数字枚举3.2 字符串枚举 三、 类型别名1. 数组别名使用2.…...

【大数据学习 | kafka】producer之拦截器,序列化器与分区器
1. 自定义拦截器 interceptor是拦截器,可以拦截到发送到kafka中的数据进行二次处理,它是producer组成部分的第一个组件。 public static class MyInterceptor implements ProducerInterceptor<String,String>{Overridepublic ProducerRecord<…...

零基础学西班牙语,柯桥专业小语种培训泓畅学校
No te comas el coco, seguro que te ha salido bien la entrevista. Ya te llamarn. 别瞎想了!我保证你的面试很顺利。他们会给你打电话的。 这里的椰子是"头"的比喻。在西班牙的口语中,我们也可以听到其他同义表达,比如&#x…...
C++学习:类和对象(三)
一、深入讲解构造函数 1. 什么是构造函数? 构造函数(Constructor)是在创建对象时自动调用的特殊成员函数,用于初始化对象的成员变量。构造函数的名称与类名相同,没有返回类型 2. 构造函数的类型 (1&…...

高阶数据结构--图(graph)
图(graph) 1.并查集1. 并查集原理2. 并查集实现3. 并查集应用 2.图的基本概念3. 图的存储结构3.1 邻接矩阵3.2 邻接矩阵的代码实现3.3 邻接表3.4 邻接表的代码实现 4. 图的遍历4.1 图的广度优先遍历4.2 广度优先遍历的代码 1.并查集 1. 并查集原理 在一…...

xxl-job java.sql.SQLException: interrupt问题排查
近期生产环境固定凌晨报错,提示 ConnectionManager [Thread-23069] getWriteConnection db:***,pattern: error, jdbcUrl: jdbc:mysql://***:3306/***?connectTimeout3000&socketTimeout180000&autoReconnecttrue&zeroDateTimeBehaviorCONVERT_TO_NUL…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...

【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...

Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...