Kotlin 从零到一

2017 年 Google 宣布 Android 为 Kotlin 提供最佳支持并且取代了 Java 的位置,Kotlin 逐渐步入大众的视野。Kotlin 项目最早可以追溯到 2010 年,JetBrains 团队准备开发一款现代化、更强大、更易用的语言,经过五年多的开发,JetBrains 终于在 2016 年年初发布了 Kotlin v1.0 版本。
至今已经过了三年多,Android 最新的官方 Demo、文档等都逐步使用 Kotlin 实现,作为 Android 开发者又怎么能被时代抛弃呢。


现在开始学 Kotlin 的一般都是有 Java 基础的,所以本文也默认读者具备一定的 Java 语言基础。Kotlin 语法跟 Java 谜之相似,毕竟同属于 Java 方言之一,并且更简洁一点,所以很多概念就不展开详细叙述了,只是把规则罗列出来。

变量/属性

  • 数组就是类,和 Java 不同,Kotlin 没有声明数组类型的特殊语法
  • 如果变量没有初始化器,需要显示的指定它的类型
  • val(来自 value)——不可变引用
  • var(来自 variable)——可变变量
  • val 变量只能进行唯一一次初始化,但是,如果编译期能确保只有唯一一条初始化语句被执行,可以根据条件使用不同的值来初始化它
  • 属性可以放到文件的顶层
  • 声明了属性的时候就声明了对应的访问器(只读属性有一个 getter,而可写属性既有 getter 又有 setter)
  • 也可以自定义访问器,自定义方式如下:
class Rectangle(val height: Int, val width: Int) {
    val isSquare: Boolean
        get() = height == width
}
  • 默认情况下,顶层属性和其他任意属性一样,是通过访问器暴露给 Java 使用的(如果是 val 就只有一个 getter,如果是 var 就对应一对 getter 和 setter)。
  • 如果想把一个常量以 public static final 修饰,可以用 const 来修饰它。
  • 扩展属性类比扩展函数
  • 扩展属性也像普通成员属性一样,必须定义 getter 函数,因为没有支持字段,因此没有默认 getter 的实现。同理,初始化也不可以,因为没有地方存储值:
var StringBuilder.lastChar: Char
    get() = get(length - 1)
    set(value: Char){
        this.setCharAt(length - 1, value)
    }

函数

  • 函数可以定义在文件的最外层,不需要把它放在类中
  • 关键字 fun 声明一个函数
  • 参数的类型写在它名字的后面
  • 返回类型放在参数列表之后
  • 当调用一个 Kotlin 定义的函数时,可以显示的标明一些参数的名称,如果在调用一个函数时,指明了一个参数的名称,为了避免混淆,那它之后的所有参数都需要标明名称
  • 声明函数的时候,指定参数的默认值,这样就可以避免创建重载函数
  • 当使用常规的调用语法时,必须按照函数声明中定义的参数顺序来给定参数,可以省略的只有排在末尾的参数,如果使用命名参数,可以省略中间的一些参数,也可以以你想要的任意顺序只给定你需要的参数。
  • Java 调用 Kotlin 函数的时候,必须显示地指定所有参数值,如果需要从 Java 代码中频繁调用,而且希望对 Java 使用者更简便,可以用 @JvmOverloads 注解它,这个指示编译期生成 Java 重载函数,从最后一个开始省略每个参数。
  • 可以把函数直接放到代码文件的顶层,不用从属于任何类
  • Kotlin 编译生成的类的名称,对应于包含函数的文件名称,这个文件中的所有顶层函数编译为这个类的静态函数。
  • 扩展函数就是一个类的成员函数,不过定义在类的外面
  • 把要扩展的类或接口名称放到即将添加的函数前,这个类的名称被称为接受者类型,用来调用这个扩展函数的那个对象,叫做接受者对象。
fun String.lastChar(): Char = this.get(this.length - 1)
  • 其中的 this 可以省略:
fun String.lastChar(): Char = get(length - 1)
  • 对于定义个扩展函数,它并不会自动的在整个项目范围内生效,需要进行导入。
  • 可以使用关键字 as 来修改导入的类或者函数名称:
import strings.lastChar as last
  • 实质上,扩展函数是静态函数,它把对象作为了它的第一个参数。
  • Java 调用扩展函数非常简单,调用这个静态函数,然后把接受者对象作为第一个参数传进去既可。
  • 这个扩展函数被称为顶层函数,会编译成一个静态函数。
  • 扩展函数的静态性质也决定了不能被重写
  • 如果一个类的成员函数和扩展函数有相同的签名,成员函数往往会被优先使用。
  • 使用 vararg 声明一个函数将有可能有任意多个数量的参数
  • 展开运算符 * 用于将任意长度的参数数组解包:
fun main(args: Array<String>){
    val list = listOf("args:", *args)
    println(list)
}
  • 使用 infix 修饰符标记函数,可使其支持中缀符号调用
infix fun Any.to(other: Any) = Pair(this, other)
val (number, name) = 1 to "one"
  • 上面的 (number,name) 为解构声明
  • 局部函数:
fun saveUser(user: User){
    fun validate(value: String, fieldName: String){
        if(value.isEmpty()){
            throw IllegalArgumentException("Can not save user ${user.id}: empty $fieldName")
        }
    }
    validate(user.name,"Name")
    validate(user.address,"Address")
    //保存 user 到数据库
}
  • 局部函数内部可直接访问外部函数的参数
  • 扩展函数也可以被声明为局部函数,但不建议使用:
fun saveUser(user: User){
    fun User.validate(value: String, fieldName: String){
        if(value.isEmpty()){
            throw IllegalArgumentException("Can not save user ${user.id}: empty $fieldName")
        }
    }
    user.validate(user.name,"Name")
    user.validate(user.address,"Address")
    //保存 user 到数据库
}

  • 只有数据没有其他代码的称为值对象
  • public 是默认属性
  • 不区分导入的是类还是函数,而且,它允许使用 import 关键字导入任何种类的生命,例如顶层函数名称
  • 可以把多个类放在同一个文件中,文件的名字还可以随意选择,Kotlin 没有对磁盘上源文件的布局加强任何限制
  • enum 是一个软关键字:只有当他出现在 class 前才有意义,在其它地方可以把它当做普通的名称来使用。
  • 可以给枚举类声明属性和方法
  • 声明类的时候,使用一个冒号(:)后面跟上接口的名称,来标记这个类实现了这个接口
  • 要改变包含 Kotlin 顶层函数的生成的类的名称,需要为这个文件添加 @JvmName 的注解,将其放入文件开头,位于包名的前面
//使用 data 修饰符表示值对象,默认为 public
data class Person(val name: String, val age: Int)

//使用 enum 创建枚举类
enum class Direction {
    EAST,
    SOUTH,
    WEST,
    NORTH
}

//定义 User 接口
interface User

//使用冒号实现/继承接口
class Student(val name: String, val age: Int, val number: Int) : User

参考文献

[1]Kotlin 实战(Kotlin in Action).北京:电子工业出版社,2017.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容