【用 Kotlin 写 Android】Kotlin Koans 深入分析讲解(上)

前言

具体 Kotlin 是什么?我相信你已经在网络上其他地方看到过解释,这里不再赘述,简单一句话:“Kotlin 是一种与 Java、C++ 平级的函数式编程语言”。在上一篇文章中,我们应该看到了,Kotlin 有很多的基础特殊的语法,让代码变得简单清晰 (可能在开始的时候你反而觉得变得复杂了),但 Kotlin 真的就是语法的改变吗?花两个小时看看 Kotlin 的语法就算学完了 Kotlin 吗?非也!Kotlin 与 Java 最大的区别是 Kotlin 的函数式编程,这一点以后我们会经常提到,Kotlin 的核心与 Java 就有本质的不同。Kotlin Koans 是学习 Kotlin 极好的学习资料,我们先把 Kotlin Koans 做一遍,相信你会对 Kotlin 有完全不同的认识。

Kotlin Koans 项目详解

Kotlin Koans 是一个 Kotlin 学习的教程,采用的方式是给你未完成的代码,给你一点提示,你去补全代码,运行单元测试,通过后进入下一题,可以非常好的学习 Kotlin。

Kotlin Koans 的安装,可以在 GitHub 上下载源代码项目,但是我不建议这样做,我建议的方式是安装 EduTools 插件,安装方式是直接在插件中心中搜索 EduTools 就可以了:

图片

然后重启 Android Studio。可以看到第一项 Browse Courses:

图片

点击选择 Kotlin Koans 项目:

图片

大约需要一分钟后,会创建项目:

图片

感觉提示,完成第一个任务:

图片

这个任务就是上一篇中函数的定义相关的内容,我们可以看到得到如下一些信息:

  1. Kotlin 文件后缀为 .kt
  2. Kotlin 文件不需要定义类,可以直接定义方法
  3. 简单的方法可以省略大括号,直接在 = 后写返回值

每一个 Task 详解

Task 2:Java to Kotlin conversion

图片

将 Java 代码转换成 Kotlin 写法。我们打开 JavaCode.java 文件,选中 toJSON 方法,复制,到 Task.kt 中粘贴(粘贴需要选中代码),粘贴后可以发现 Java 代码自动转换成了 Kotlin 代码,很方便。

图片

图片

除了上面这种方法,还可以用 Android Studio 中代码装换工具,将 Java 文件转换成 Kotlin:

图片

图片

我们在这里注意几个问题:

  1. 函数的定义,用 fun 关键字
  2. 参数先写参数名,再写参数类型,中间用冒号 : 分割
  3. 方法参数后和大括号中间需要写函数返回值类型,用 : 说明
  4. 创建对象没有 new 关键字,直接类名后跟括号创建新对象
  5. 属性定义用 val(不可更改) 或 var(可以更改)

Task 3:Named arguments

图片

Kotlin 中参数是可以有默认值的,并且在调用的时候,可以显示声明哪些变量用哪些值,而不一定必须要按顺序赋值,其他的值使用默认值,很方便灵活,这样就可以减少构造函数、重载函数的数量。Java 中两个重载函数参数的类型如果都一样的话,是不允许的,但是 Kotlin 使用默认值的方式就可以很好的避免这个问题(声明一个三个参数的方法,并加上默认值,调用的时候对不同的参数进行声明赋值,就可以达到 Java 需要多个不同类型从在才能达到的目的)。

/**
 * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied.
 *
 * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit]
 * elements will be appended, followed by the [truncated] string (which defaults to "...").
 */
public fun <T> Iterable<T>.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): String {
    return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString()
}

图片

Task 4:Default arguments

图片

看题目可以看出,有些方法在调用的时候报错,提示有些值没有别赋值,那我们的任务就是在函数定义的时候加上合适的默认值,分析提示给出的 Java 代码,我们可以看到,最后一个如果 number 没有被赋值,会用默认值 42 调用第二个方法,而第二个方法 toUpperCase 没有被赋值,使用默认值 false 调用第一个方法,则可以写出答案:

图片

图片

在这里我们可以看到合理的使用默认值,可以极大的简化代码。

Task 5:Lambdas

图片

找偶数很简单,每一个都分别除 2 看余数是否为 0,但是刚刚看到这道问题可能会摸不着头脑,怎么写,这什么意思呀?题目名称叫 Lambdas,Java 8 中支持 Lambda 表达式,Kotlin 也同样支持,怎么写呢。如果想解决这个问题,我们最好解决几个概念:

  • 函数在 Kotlin 中是一等公民(First-class function)
    • 函数可以像变量一样传递给其他函数作为参数(某一个函数有参数,这个参数是一个变量)
    • 函数可以作为其他函数的返回值
    • 函数可以用于给变量赋值可以存储在数据结构中
  • 高阶函数(Higher-Order Functions)
    • 函数作为函数的参数
    • 函数作为函数的返回值
  • 函数式编程(Functional programming)
    • 函数式编程是和面向对象、面向过程同一级别的编程方法或编程模式
    • 函数是一等公民是函数式编程的必要条件,经常用在高阶函数中
    • 后面我们会有单独的文章介绍函数式编程

图片

我们可以看到 any 函数的定义,predicate 参数是一个函数,这个函数的返回值是一个 Boolean 类型的值:

图片

图片

图片

图片

简化到最后,就很简单了。有没有觉得函数式编程特别神奇呢?

Task 6:Strings

图片

Kotlin 字符串可以像 Java 一样,也可以用三个双引号声明,三个双引号声明的字符串其中可以包含多行。字符串模板可以很方便在字符串中使用变量,则这个题的答案就是:

图片

这里我们用了 trimIndent() 方法对缩进进行格式化,还可以使用 trimMargin(),如下图,其中的竖线 | 是trimMaring 默认格式化特殊字符:

图片

Task 7:Data classes

图片

Date Class 是什么东西?我们先来了解 Kotlin 中集中数据结构:

  • Class
    • 与 Java 类类似,是一种数据结构
    • Kotlin 中的 Class 继承自 Any,而不是 Object
    • 用关键字 constructor 声明构造函数,够着函数可以有默认值
    • 构造函数分为主构造函数和二级构造函数,主构造函数跟在类名后由关键字 constructor 和参数表共同构成,二级构造函数在类中,用 constructor 和参数列表构成,注意如果有主构造函数,二级函数必须调用主构造函数。如 constructor(name: String, parent: Person) : this(name)
    • 主构造函数无法执行代码,如果需要执行一些代码时,可以用 init{} 在类中执行,可以声明多个 init{},执行顺序与声明顺序一致。
    • 默认类不可以被集成,方法不可以被重写,如果希望类被继承或方法可以被重写,可以在类或方法前加 open 关键字。
    • 子类在重写父类方法时,需要在方法前加 override 关键字
    • super 关键字调用父类方法
    • abstract 关键字定义抽象类,interface 关键字定义接口。
    • 普通情况下,类没有静态方法,如果需要静态发发或所有静态属性,需要用伴随对象 companion object,相当于独立于类开辟了一块空间,所有对象共有。
  • Properties and Fields
    • val 修改不可更改的属性
    • var 修饰可以更改的属性
    • lateinit 修饰延迟加载的属性,在需要用的时候才初始化。
  • Data Class
    • 有些时候,创建类就是为了让其可以有几个属性,Java 中的 Bean 对象,而在 Kotlin 中,将这种数据结构单独定义为 data class
    • 其中会自动创建一些方法,如 copy()equals()
    • 我们在后面会有主题讲解 data class

图片

data class 可以很简单的定义数据结构,并且其中自动包含了 get/set 方法,易读且方便。

Task 8:Nullable type

图片

Java 中经常需要判空,如果不为空,获取其中某些属性值等,写起来不优雅,且不安全,Kotlin 中采用了更简单的方式。

图片

注意,这并不意味着 Kotlin 中就完全不需要关心变量为空引起的错误,我们后面会具体详细说明一些 Java 代码转成 Kotlin 或直接 写 Kotlin 代码引起的一些错误,是一个需要填的坑。

Task 9:Smart casts

图片

自动类型转换是一个很聪明的特性。Kotlin 中没有 switch-case,代替它的是 when,这里的例子是判断 expr 具体是哪一种类型,这里可以展现出 Kotlin 强大的是在判断一个对象是哪一种类型后,后面这个变量直接转换成该类型,而不像 Java 中需要强转。

图片

Task 10:Extension functions

图片

扩展函数。有些时候,某些类功能不够强大,你希望扩展这个类,而你又不能修改该类的源代码,如果是 Java,你可能需要继承自功能不够强大的类,添加新方法,然后使用新的类,这比较麻烦,也可能会因为需求的变更,这个类越来越不好维护。Kotlin 的方式是在不修改原来的类的代码的情况下,扩展方法出新的方法,使用起来就像是在原来的类中添加了新的方法。

图片

在没有修改 Int 和 Pair 对象的情况下,他们都有了转成有理数的方法了。

Task 11:Object expressions

图片

对象表达式。Kotlin 的对象表达式与 Java 中的匿名内部类差不多。有些情况只用一次的对象,没必要写成一个类。

图片

简化代码改为 Lambda 表达式:

图片

再简化代码,使用 Kotlin stdlib:

图片

了解越多 Kotlin stdlib 中的方法,写代码越快,效率越高。

Task 12:Extension functions on collections

Kotlin 在集合类中做了大量的优化,提供了大量的有用的方法,这里排序可以直接调用。

/**
 * Returns a list of all elements sorted descending according to their natural sort order.
 */
public fun <T : Comparable<T>> Iterable<T>.sortedDescending(): List<T> {
    return sortedWith(reverseOrder())
}

Kotlin 提供了自然序的升序降序排序方法:sortedDescending

图片

Task 13:Comparison

图片

我们定义了一个类 MyDate,我们现在直接用 < 对这个类的对象比较大小。我们需要对这个对象定义比较大小操作符,则只需重写 compareTo 方法就可以了。

图片

Task 14:Task In range

图片

有了上面的经验,这里只需了解 in 操作符是调用的 contains 方法就可以了:

图片

简写成(其中 .. 就是执行 rangeTo 方法):

图片

Task 15:Range to

图片

图片

图片

我们在上一个任务中,有编译器自动提示使用了 in - .. 操作符,我们点进去看看,发现其实就是执行了 rangeTo 方法,这一个任务中,我们就需要实现 rangeTo 方法就可以,rangeTo 方法返回值是 ClosedRange,而 ClosedRange 需要对象实现比较大小 compareTo 方法,恰好我们上一节中已经在 MyData 中实现了 compareTo,恰好 DateRange 实现了 ClosedRange,因此我们可以直接使用,结果如下:

图片

这个任务比较复杂,但是逻辑是很清晰的。

Task 16:For loop

图片

For 循环需要迭代器,DateRange 需要实现 Iterable,则问题就简单了:

图片

当然,可以优化代码:

图片

For 循环就是迭代器的遍历。

Task 17:Operators overloading

图片

+ 操作符,其实就是实现 plus 方法。* 操作符就是实现 times 方法

图片

Task 18:Destructuring declarations

图片

可以将对象属性值赋值给其他对象,要求这个对象必须由 data 修饰。

图片

Task 19:Invoke

图片

图片

小结

本文主要了解了一些 Kotlin 的具体实现方法,对真正写 Kotlin 程序极有好处。

到这里,我们完成了一半的任务,为避免篇幅过长,下面的任务我们在下一篇文章中继续讨论。


如果有一天你觉得过的舒服了,你就要小心了!欢迎关注我的公众号:我是任玉琢

qrcode_for_gh_45402a07f7d9_258

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
当然可以!以下是一个使用KotlinAndroid Studio中编的简单登录界面的示例: 首先,在res/layout目录下创建一个名为activity_login.xml的布局文件,用于定义登录界面的UI元素。可以像这样编: ```xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp"> <EditText android:id="@+id/editTextUsername" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Username" android:inputType="text" /> <EditText android:id="@+id/editTextPassword" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Password" android:inputType="textPassword" /> <Button android:id="@+id/buttonLogin" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Login" /> </LinearLayout> ``` 然后,在MainActivity.kt文件中,设置布局并处理登录逻辑。可以像这样编: ```kotlin import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import kotlinx.android.synthetic.main.activity_login.* class LoginActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_login) buttonLogin.setOnClickListener { val username = editTextUsername.text.toString() val password = editTextPassword.text.toString() if (isValidCredentials(username, password)) { // 登录成功 // 在这里添加你的登录逻辑 } else { // 登录失败 // 在这里处理登录失败逻辑 } } } private fun isValidCredentials(username: String, password: String): Boolean { // 在这里添加验证逻辑,例如检查用户名和密码是否匹配 return username == "admin" && password == "password" } } ``` 这里使用了`kotlinx.android.synthetic`插件来简化对UI元素的访问。请确保在build.gradle文件中启用了插件依赖,例如: ```groovy android { // ... // 添加以下配置 viewBinding { enabled = true } } ``` 这是一个简单的登录界面示例,你可以根据自己的需求进行修改和扩展。希望能帮到你!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值