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

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中,使用valvar关键字来声明变量。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引入了一些新的数据类型,如StringIntBoolean等。这些数据类型是不可变的,也就是说,一旦创建,就不能再修改。总的来说,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属性,表示尺寸的值。这样,我们就可以直接使用Intdp属性来创建一个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,包含两个属性nameage。这样,我们就可以直接创建一个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,包含三个枚举常量REDGREENBLUE。这样,我们就可以直接使用枚举常量,而不需要手动定义常量。

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)

这里全局函数addsubtract都是函数类型(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,包含两个属性xy。然后重载了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开放能力简介的课后习题

不出户&#xff0c;知天下&#xff1b; 不窥牖&#xff0c;见天道。 其出弥远&#xff0c;其知弥少。 是以圣人不行而知&#xff0c;不见而明&#xff0c;不为而成。 本篇<HarmonyOS第一课>HarmonyOS SDK开放能力简介是简单介绍了HarmonyOS SDK&#xff0c;不需要大家过多…...

深度学习:yolo的使用--图像处理

定义了一个名为 ListDataset 的类&#xff0c;它继承自 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是拦截器&#xff0c;可以拦截到发送到kafka中的数据进行二次处理&#xff0c;它是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. 别瞎想了&#xff01;我保证你的面试很顺利。他们会给你打电话的。 这里的椰子是"头"的比喻。在西班牙的口语中&#xff0c;我们也可以听到其他同义表达&#xff0c;比如&#x…...

C++学习:类和对象(三)

一、深入讲解构造函数 1. 什么是构造函数&#xff1f; 构造函数&#xff08;Constructor&#xff09;是在创建对象时自动调用的特殊成员函数&#xff0c;用于初始化对象的成员变量。构造函数的名称与类名相同&#xff0c;没有返回类型 2. 构造函数的类型 &#xff08;1&…...

高阶数据结构--图(graph)

图&#xff08;graph&#xff09; 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问题排查

近期生产环境固定凌晨报错&#xff0c;提示 ConnectionManager [Thread-23069] getWriteConnection db:***,pattern: error, jdbcUrl: jdbc:mysql://***:3306/***?connectTimeout3000&socketTimeout180000&autoReconnecttrue&zeroDateTimeBehaviorCONVERT_TO_NUL…...

jmeter压测工具环境搭建(Linux、Mac)

目录 java环境安装 1、anaconda安装java环境&#xff08;推荐&#xff09; 2、直接在本地环境安装java环境 yum方式安装jdk 二进制方式安装jdk jmeter环境安装 1、jmeter单机安装 启动jmeter 配置环境变量 jmeter配置中文 2、jmeter集群搭建 多台机器部署jmeter集群…...

docker设置加速

sudo tee /etc/docker/daemon.json <<-‘EOF’ { “registry-mirrors”: [ “https://register.liberx.info”, “https://dockerpull.com”, “https://docker.anyhub.us.kg”, “https://dockerhub.jobcher.com”, “https://dockerhub.icu”, “https://docker.awsl95…...

使用requestAnimationFrame写防抖和节流

debounce.ts 防抖工具函数: function Animate() {this.timer null; }Animate.prototype.start function (fn) {if (!fn) {throw new Error(需要执行函数);}if (this.timer) {this.stop();}this.timer requestAnimationFrame(fn); }Animate.prototype.stop function () {i…...

Puppeteer 与浏览器版本兼容性:自动化测试的最佳实践

Puppeteer 支持的浏览器版本映射&#xff1a;从 v20.0.0 到 v23.6.0 自 Puppeteer v20.0.0 起&#xff0c;这个强大的自动化库开始支持与 Chrome 浏览器的无头模式和有头模式共享相同代码路径&#xff0c;为自动化测试带来了更多便利。从 v23.0.0 开始&#xff0c;Puppeteer 进…...

Java方法重写

在Java中&#xff0c;方法重写是指在子类中重新定义父类中已经定义的方法。以下是Java方法重写的基本原则&#xff1a; 子类中的重写方法必须具有相同的方法签名&#xff08;即相同的方法名、参数类型和返回类型&#xff09;。子类中的重写方法不能比父类中的原方法具有更低的…...

vscode通过.vscode/launch.json 内置php服务启动thinkphp 应用后无法加载路由解决方法

我们在使用vscode的 .vscode/launch.json Launch built-in server and debug 启动thinkphp应用后默认是未加载thinkphp的路由文件的&#xff0c; 这个就导致了&#xff0c;某些thinkphp的一些url路由无法访问的情况&#xff0c; 如http://0.0.0.0:8000/api/auth.admin/info这…...

Webserver(2.6)有名管道

目录 有名管道有名管道使用有名管道的注意事项读写特性有名管道实现简单版聊天功能拓展&#xff1a;如何解决聊天过程的阻塞 有名管道 可以用在没有关系的进程之间&#xff0c;进行通信 有名管道使用 通过命令创建有名管道 mkfifo 名字 通过函数创建有名管道 int mkfifo …...

四足机器人实战篇之一:波士顿spot机器人工程实现分析

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录前言一、机器人发展历史二、硬件系统及电机执行器篇硬件系统电机执行器传感器机处理器电气连接三、感知(视觉点云、局部地图、定位)篇1.深度相机获取…...

TensorFlow 预训练目标检测模型集合

Tensorflow 提供了一系列在不同数据集上预训练的目标检测模型&#xff0c;包括 COCO 数据集、Kitti 数据集、Open Images 数据集、AVA v2.1 数据集、iNaturalist 物种检测数据集 和 Snapshot Serengeti 数据集。这些模型可以直接用于推理&#xff0c;特别是当你对这些数据集中已…...

字符串的区别

C 和 Java 字符串的区别 最近 C 和 Java 在同步学习&#xff0c;都有个字符串类型&#xff0c;但二者不太一样&#xff0c;于是就做了些许研究。 在编程中&#xff0c;字符串作为数据类型广泛应用于不同的场景。虽然 C 和 Java 都允许我们处理字符串&#xff0c;但它们在字符…...