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 项目:

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

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

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

Kotlin 文件后缀为

Kotlin 文件不需要定义类,可以直接定义方法

简单的方法可以省略大括号,直接在 后写返回值

每一个 Task 详解

Task 2:Java to Kotlin conversion

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

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

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

函数的定义,用 fun 关键字

参数先写参数名,再写参数类型,中间用冒号 分割

方法参数后和大括号中间需要写函数返回值类型,用 说明

创建对象没有 关键字,直接类名后跟括号创建新对象

属性定义用 val(不可更改) 或 var(可以更改)

Task 3:Named arguments

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

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 一样,也可以用三个双引号声明,三个双引号声明的字符串其中可以包含多行。字符串模板可以很方便在字符串中使用变量,则这个题的答案就是:

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

Task 7:Data classes

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

Class

与 Java 类类似,是一种数据结构

Kotlin 中的 Class 继承自 Any,而不是 Object

用关键字 constructor 声明构造函数,够着函数可以有默认值

构造函数分为主构造函数和二级构造函数,主构造函数跟在类名后由关键字 constructor 和参数表共同构成,二级构造函数在类中,用 constructor 和参数列表构成,注意如果有主构造函数,二级函数必须调用主构造函数。如 。

主构造函数无法执行代码,如果需要执行一些代码时,可以用 在类中执行,可以声明多个 ,执行顺序与声明顺序一致。

默认类不可以被集成,方法不可以被重写,如果希望类被继承或方法可以被重写,可以在类或方法前加 关键字。

子类在重写父类方法时,需要在方法前加 关键字

关键字调用父类方法

关键字定义抽象类, 关键字定义接口。

普通情况下,类没有静态方法,如果需要静态发发或所有静态属性,需要用伴随对象 ,相当于独立于类开辟了一块空间,所有对象共有。

Properties and Fields

val 修改不可更改的属性

var 修饰可以更改的属性

lateinit 修饰延迟加载的属性,在需要用的时候才初始化。

Data Class

有些时候,创建类就是为了让其可以有几个属性,Java 中的 Bean 对象,而在 Kotlin 中,将这种数据结构单独定义为

其中会自动创建一些方法,如 , 等

我们在后面会有主题讲解

用 可以很简单的定义数据结构,并且其中自动包含了 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 在集合类中做了大量的优化,提供了大量的有用的方法,这里排序可以直接调用。

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

Task 13:Comparison

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

Task 14:Task In range

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

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

Task 15:Range to

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

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

Task 16:For loop

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

当然,可以优化代码:

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

Task 17:Operators overloading

操作符,其实就是实现 方法。 操作符就是实现 方法

Task 18:Destructuring declarations

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

Task 19:Invoke

小结

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

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

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

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180409G0BOFL00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

同媒体快讯

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励