kotlin基础

来源:互联网 发布:农村淘宝 编辑:程序博客网 时间:2024/04/28 18:49

kotlin 语言特性

  • kotlin中一切皆为对象 
    • 没有像java一般的基本数据类型,数值类型为:Int, Float, Double等
    • 函数也是对象,可作为参数和返回值
    • 自然就会有高阶函数和lambda

语法特性及规范

  • 语句结尾不用分号
  • 使用驼峰命名,尽量避免下划线
  • public函数应当有说明文档
  • lambda中花括号内前后都应该有空格

一、变量

1. 变量声明:

  • 只读变量: val a: Int = 0
  • 可变变量: var b: String = "Kotlin" 
    在kotlin中,变量类型是写在变量名之后的,用英文冒号 : 隔开,类型声明不是必须的,如果后面的值是一个明显可识别的类型,就不必添加类型声明。 
    例如,以上声明可直接这么写: 
    val a = 0 
    val b = "Kotlin"

2. 变量使用的一些特性

  • 空值安全检查 
    var s: String? = null 
    当一个变量允许为空值时,必须显示地使用 ? 来进行声明,? 置于类型名之后,否则,在编写时该变量出现空值就会直接报错。 
    例如: var s: String = null 这一语句会直接报错,不用等到编译时检查

    • 此外,对于nullable values, 可以在调用的时候进行安全检查,例如,有一个User类,要获取类中的name属性

      <code class="language-java hljs  has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>( user != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>)name = user.getName()<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>name = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

      在kotlin中:

      <code class="language-kotlin hljs javascript has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">var</span> name: <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span>? = user?.getName()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 当user不为空的时候执行getName()</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

      当然,在kotlin中的数据类并不需要显式调用getter和setter方法,通常情况下都只需要直接使用属性名:var name: String? = user?.name

    • 还可以进行链式调用: user?.name?.toUpperCase() // 当user和name都为null的时候表达式值为null

    • Elvis Operator ?: 
      var url = urlList.get(pos) ?: return null 
      当?:左边表达式不为空时,返回表达式的值,否则执行?:右边表达式的值 
      也可以使用if… else…语句 
      val url = if(pos < urlList.size()) urlList.get(pos) else return null
    • 安全类型转换: 
      var linearLayout = viewGroup as? LinearLayout 
      正常情况下无法转换失败将抛出异常,进行类型安全检查之后不会抛出异常,而是返回了null,所以此时的接收变量也应当为nullable

二、语句

  • if, else等条件判断语句与java相同
  • 没有switch语句,取而代之的是when语句:

    <code class="language-kotlin hljs coffeescript has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">when</span>(obj){   <span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">//</span> 这里是lambda表达式    <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span><span class="hljs-function" style="box-sizing: border-box;"> -></span> println(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"zero or one"</span>)      <span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">//</span> 只有同种数据类型才能够这么写,应该是用泛型列表实现的    <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span><span class="hljs-function" style="box-sizing: border-box;"> -></span> println(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"one"</span>)    <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"hello"</span><span class="hljs-function" style="box-sizing: border-box;"> -></span> println(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"hello"</span>)    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">is</span> String<span class="hljs-function" style="box-sizing: border-box;"> -></span> println(obj)    !<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">is</span> Long<span class="hljs-function" style="box-sizing: border-box;"> -></span> println(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"not a long value"</span>)    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span><span class="hljs-function" style="box-sizing: border-box;"> -></span> println(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"other value"</span>)    <span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">//</span> 相当于<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">switch</span>中的<span class="hljs-reserved" style="box-sizing: border-box;">default</span>,可以省略}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

    可以看出,when语句可以可以接收多种数据类型,不像switch只能够接收int型(jdk 1.7以后支持字符串,但实际上是通过比较hashCode来实现的,实际上还是int) ,但也有不足之处,即不能够像switch那样顺序执行,遇到break才中断

  • 循环语句

    • for循环:Java中的foreach,(跟Python几乎一样)

      <code class="language-kotlin hljs r has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(news <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> newsList){}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(idx <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.</span>.array.lastIndex){}  // ..表示范围,即可以用数字,也可以使用英文字母,如:a..z<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(i <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span> until <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>){}    // 左闭右开区间,这里即不包括<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(i <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">.100</span> step <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>){}    // step定义步长,这里为:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span> , <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">99</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(i <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span> downTo <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>){}    // downTo 很容易理解,作用相当于--,但也可以和step结合使用</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>
    • while和do…while语句和java一样

  • 跳转语句

    • break 和 continue,首先可以像Java里的那么使用
    • kotlin里的break, continue和 return还可以使用label来跳转(怎么看着像go语句了) 
      这里只举使用label的例子: 
      <code class="language-kotlin hljs r has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;">loop@ <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (i <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">.100</span>) {    // 这里的loop是label名,可以自定义    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (j <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">.100</span>) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>)            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>@loop    }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

    需要注意的是,使用label时,break, continue只能用在循环中,return不能用在循环中

三、函数

定义

函数定义使用fun关键字

<code class="language-kotlin hljs fsharp has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">fun</span> add(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">val</span> x: Int, y: Int) : Int /* 这里是返回值类型 */{    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 默认返回类型为Unit(不是null),没有什么实际意义,可以不用写</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 函数参数可以不用写val,但不能使用var</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> x + y}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>

上述函数中只有一个表达式,可以简写为: 
fun add(x: Int, y: Int) : Int = x + y

lambda

lambda表达式的作用相当于一个函数,但可以大大地简化代码,特别是在Android中设置各种listener的的时候。 
这里先用上面的例子来说明,上面的例子用lambda可以写成: 
val add: (Int, Int) -> Int = {x , y/*这里是参数*/ -> x + y} 
这尼玛不是忽悠人吗,代码明明增多了还说减少 
且慢,先看一下android中无比常用的setOnClickListener: 
使用java:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;">button.setOnClickListener(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> OnClickListener(){    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onClick</span>(View v){       ...    }})</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

再看看kotlin:

<code class="language-kotlin hljs avrasm has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;">button<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setOnClickListener</span>{ v -> if(v<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.isEnable</span>) v<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.isEnable</span> = false }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

怎么样,是不是简单了好多 
等等,不对啊,怎么setOnClickListener方法没有参数了,变成了{},这是什么鬼 
那是因为在kotlin中, 
如果函数的最后一个参数是函数,那么这个参数可以直接写在圆括号外面(要用花括号), 
如果只有一个函数参数,可以直接省略圆括号!

还有更简单的呢:

<code class="language-kotlin hljs cs has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;">button.setOnClickListener{ <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(v.isEnable) v.isEnable = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span> } <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 再lambda中,如果只有一个参数,那么可以使用it来表示,而不用写参数声明</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

各种单个函数当接口,如android中许多listener,runnable等都可以使用lambda表达式来简化

默认参数值函数

即可以为某个参数设定默认值,如:

<code class="language-kotlin hljs vbscript has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;">fun read(b: <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Array</span><Byte>, off: <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Int</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">len</span>: <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Int</span> = b.size()) {}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

专用类型函数(没有这说法,标题我自己起的。。)

  • 内联函数:即把函数调用语句直接替换成函数体,省去了调用函数的时间开销,当增加了空间开销,故一般只对函数体较小的函数进行内联 
    关键字:inline

    <code class="language-kotlin hljs oxygene has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">inline</span> fun <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">add</span>(x: Int, y: Int): Int = x + y<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">add</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>)    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 调用语句被替换成 3 + 5</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>
  • 中缀函数 
    关键字:infix

    <code class="language-kotlin hljs delphi has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;">infix fun Int.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">shl</span>(bitCounts : Int): Int<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">{}</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">shl</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 跟 1.shl(2) 相同</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>
  • 尾递归函数: 编译器会对尾递归函数进行优化以获得更好的性能

    • 要求:递归调用语句必须是函数最后一句 
      关键字: tailrec 
      <code class="language-kotlin hljs haml has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;">tailrec fun findFixPoint(x: Double = 1.0): Double    =<span class="ruby" style="box-sizing: border-box;"> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (x == <span class="hljs-constant" style="box-sizing: border-box;">Math</span>.cos(x)) x <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> findFixPoint(<span class="hljs-constant" style="box-sizing: border-box;">Math</span>.cos(x))</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

四、类和接口

  • 基础杂项

    • 定义及初始化:使用class关键字定义

      <code class="language-kotlin hljs delphi has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 写在类名后的constructor()是主构造方法(primary constructor)</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> User <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">constructor</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(name: <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">String</span>)</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">{    init {    //由于primary constructor中不能初始化(不能写表达式),一般初始化工作都写在init代码块中,init 是一个关键字        logger.info("User initialized with name: ${name}</span>")    }}   // 构造方法没有参数可以省略<span class="hljs-title" style="box-sizing: border-box;">constructor</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">()</span>,类没有具体实现可以省略<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">{}</span>// 可以写成:<span class="hljs-title" style="box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box;">User</span></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul>

      除了primary constructor 外,其余构造方法称为secondary constructors
      上面都User类,用secondary constructor可以改写为:

      <code class="language-kotlin hljs javascript has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> User{    constructor(name: <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span>){        logger.info(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"User initialized with name: ${name}"</span>)    }}<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 如果一个类有primary constructor,那么所有的secondary constructor都应该实现(或者说委托, delegate)primary constructor.</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> User constructor(name: <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span>){    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">var</span> name: <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span> = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">""</span>    constructor(name: <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span>, age: Int): <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>(name){        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 这里的name和primary constructor的name不是同一个,跟成员变量name也不是同一个</span>    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 也可以直接赋常量值,反正目的就是初始化</span>    constructor(age: Int, address: <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span>): <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"dongdong"</span>){    }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li></ul>
    • 类属性 
      kotlin类属性默认都会自动生成get()和set(value)方法的,我们仅在需要指定条件时才重写。

      <code class="language-kotlin hljs actionscript has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">A</span>{</span>      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">var</span> name: String          <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">get</span>() = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Tom"</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 注意:这里一旦写成定值,set方法将失效,因为每次调用name实际上都是调用其get()方法的</span>          <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">set</span>(value){                  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 这里可以根据需要添加各种条件判断</span>          }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>
    • 继承 
      由于kotlin中所有类和方法默认都是final的,不能直接继承或重写,需要继承的类或类中要重写的方法都应当在定义时添加open关键字

      <code class="language-kotlin hljs fsharp has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">open</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> Parent(name: String){      var name: String      init{              this.name = name    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 如果没有初始化,就必须声明为abstract</span>              <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 也可以声明的时候进行初始化:var name = "dongdong"</span>      }      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">fun</span> showChildren(){}    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 没有加open关键字,默认为final方法,不能重写,但可以重载</span>      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">open</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">fun</span> showIdentity(){}    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 可以重写或重载</span>}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> Child(name: String): Parent(name){      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">fun</span> showIdentity(){}  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 使用override关键字,习惯上写成一行,不像java是使用注解分开写</span>}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul>

      注意这里使用父类名+() 来表示了primary constructor,同样也可以使用super关键字来实现,亲测两种实现方法可以互换,这里的super跟java的super相似:

      <code class="language-kotlin hljs haskell has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-type" style="box-sizing: border-box; color: rgb(102, 0, 102);">Child</span>: <span class="hljs-type" style="box-sizing: border-box; color: rgb(102, 0, 102);">Parent</span>{      constructor<span class="hljs-container" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">name</span>: <span class="hljs-type" style="box-sizing: border-box; color: rgb(102, 0, 102);">String</span>)</span>: super<span class="hljs-container" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">name</span>)</span>{}}</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

      kotlin中所有类都有一个共同的父类: Any(注意这不是java.lang.Object), 这个类只有equals(), hashCode(), toString()方法。 
      kotlin与java一样,只能单继承,但可以实现多个接口。

    • 抽象 
      kotlin的抽象与java的抽象的规则基本一致:

      • 使用abstract关键字
      • 抽象方法必须声明在抽象类中
      • 有抽象属性(即抽象变量,像上面说的那个name属性,这一点与java不同)
      • 可以把非抽象父类的方法重新声明为抽象方法(倒是没试过java行不行)
      • 非抽象子类必须实现抽象父类的所有抽象方法
  • 接口 
    同样使用 interface 关键字 
    很奇怪,kotlin的接口跟Java抽象类几乎一样,可以定义有方法体的方法!

    • 接口可以多继承
    • 接口中的属性不能初始化
  • Object 
    对于object 关键字,刚开始接触可能不太好理解,其实就是类似于java的匿名内部类,因为kotlin没有匿名内部类,不能这样创建实例:User("hello"){},主要用处有:

    1. 当需要对一个类进行轻微的改动时,避免重新创建子类而使用
    2. 实现单例。 
      首先最基本用法:(这里使用listener举例,但实际的listener并不用这么写) 
      这时叫companion expression, 是即时加载

      <code class="language-kotlin hljs cs has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;">button.setOnClickListener(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">object</span>: OnClickListener {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">override</span> fun onClick(v: View?){}})</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

      object关键字的声明也可以进行继承:

      <code class="language-kotlin hljs cs has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;">    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">interface</span> A{}        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">object</span>: Base(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"name"</span>), A{}    </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

      单例实现(这个时候叫companion declarations, 是惰性加载的): 
      kotlin单例实现很简单,只需要使用object 关键字后面加一个单例的名称即可:

      <code class="language-kotlin hljs r has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;">object DefaultListener : MouseAdapter() {     override fun mouseClicked(e: MouseEvent) {     // <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>}     override fun mouseEntered(e: MouseEvent) {     // <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>     }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>
      • companion object 
        companion关键字仅有这个用法,companion object只能在类中使用,相当于java中的静态内部类(kotlin没有static关键字),这里摘取kotlin文档的例子: 
        <code class="language-kotlin hljs scala has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">MyClass</span> {</span>    companion <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">object</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Factory</span> {</span>        fun create(): MyClass = MyClass()    }}<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 使用</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">var</span> instance = MyClass.create()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 也可以使用下面的方法来调用</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 由于Factory定义后不可修改,故使用val变量来存放</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">val</span> factory = MyClass.Factory<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">var</span> instance = factory.create()</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul>

    companion object后的名字可以省略(反正暂时我还是觉得没什么卵用, 直接通过类名使用即可了),省略后会有一个默认的名字Companion 
    companion object是在类加载的时候初始化的

    • sealed class 
      新东西,看下文档先:

      Sealed classes are used for representing restricted class hierarchies, when a value can have one of the types from a limited set, but cannot have any other type. They are, in a sense, an extension of enum classes: the set of values for an enum type is also restricted, but each enum constant exists only as a single instance, whereas a subclass of a sealed class can have multiple instances which can contain state.

      说白了,就是一个内部元素为类的枚举,并且内部的类都是本身的子类。sealed class 只能有一个实例,但是其子类跟普通的类一样,可以有多个实例,也可以在任何地方被继承。 
      sealed class 的直接子类必须放在sealed class内,但sealed class内部可以有任意类(但一般只放置其子类)。

      <code class="language-kotlin hljs haskell has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-title" style="box-sizing: border-box;">sealed</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-type" style="box-sizing: border-box; color: rgb(102, 0, 102);">Expr</span> {<span class="hljs-class" style="box-sizing: border-box;">    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-type" style="box-sizing: border-box; color: rgb(102, 0, 102);">Const</span><span class="hljs-container" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">val</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">number</span>: <span class="hljs-type" style="box-sizing: border-box; color: rgb(102, 0, 102);">Double</span>)</span> : <span class="hljs-type" style="box-sizing: border-box; color: rgb(102, 0, 102);">Expr</span><span class="hljs-container" style="box-sizing: border-box;">()</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-type" style="box-sizing: border-box; color: rgb(102, 0, 102);">Sum</span><span class="hljs-container" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">val</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">e1</span>: <span class="hljs-type" style="box-sizing: border-box; color: rgb(102, 0, 102);">Expr</span>, <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">val</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">e2</span>: <span class="hljs-type" style="box-sizing: border-box; color: rgb(102, 0, 102);">Expr</span>)</span> : <span class="hljs-type" style="box-sizing: border-box; color: rgb(102, 0, 102);">Expr</span><span class="hljs-container" style="box-sizing: border-box;">()</span>    object <span class="hljs-type" style="box-sizing: border-box; color: rgb(102, 0, 102);">NotANumber</span> : <span class="hljs-type" style="box-sizing: border-box; color: rgb(102, 0, 102);">Expr</span><span class="hljs-container" style="box-sizing: border-box;">()</span>    // 也可以:    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-type" style="box-sizing: border-box; color: rgb(102, 0, 102);">Sub</span>{}}</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

      sealed class有什么用呢,可以发现,sealed class 和 when 更配哦:

      <code class="language-kotlin hljs coffeescript has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;">fun eval(<span class="hljs-attribute" style="box-sizing: border-box; color: rgb(0, 136, 0);">expr</span>: Expr): Double = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">when</span>(expr) {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">is</span> Expr.Const<span class="hljs-function" style="box-sizing: border-box;"> -></span> expr.number    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">is</span> Expr.Sum<span class="hljs-function" style="box-sizing: border-box;"> -></span> eval(expr.e1) + eval(expr.e2)    Expr.NotANumber<span class="hljs-function" style="box-sizing: border-box;"> -></span> Double.NaN        <span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">//</span> the `<span class="javascript" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span></span>` clause <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">is</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">not</span> required         <span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">//</span>because we<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'ve covered all the cases}</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>
  • data class 
    kotlin中有专门的数据类来代替java中的JavaBean,再也不用写JavaBean的getter和setter了

    <code class="language-kotlin hljs haskell has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-typedef" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">data</span> class <span class="hljs-type" style="box-sizing: border-box; color: rgb(102, 0, 102);">News</span><span class="hljs-container" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box;">title</span>: <span class="hljs-type" style="box-sizing: border-box; color: rgb(102, 0, 102);">String</span>, <span class="hljs-title" style="box-sizing: border-box;">time</span>: <span class="hljs-type" style="box-sizing: border-box; color: rgb(102, 0, 102);">String</span>)</span></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

    简单粗暴,连{}都省了,而且编译器还会自动生成该类的equals(), hashCode(), copy(), toString() 方法。

  • Delegated Properties 
    三种基本用法:

    lazy properties: the value gets computed only upon first access, 
    observable properties: listeners get notified about changes to this property, 
    storing properties in a map, not in separate field each.

即: 
1. 延迟加载,仅在第一次使用时加载 
2. 可被观察属性 
3. 存储 
要求,必须提供getValue()(和setValue(value), 如果是mutable的,即var变量)方法

<code class="language-kotlin hljs javascript has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;">    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> Example {      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">var</span> p: <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span> by Delegate()    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> Delegate {          operator fun getValue(thisRef: Any?, property: KProperty<*>): <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span> {                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"$thisRef, thank you for delegating '${property.name}' to me!"</span>          }          operator fun setValue(thisRef: Any?, property: KProperty<*>, value: <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span>) {                println(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"$value has been assigned to '${property.name} in $thisRef.'"</span>)          }    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 使用</span>    val e = Example()    println(e.p)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li></ul>

标准库的delegates有lazy, Delegates.observable(), map, 暂时不细说了,有兴趣看官方文档

扩展函数及扩展属性(Extension Functions and Extension Properties)

这个真的非常非常好用,特别拿出来说。 
这里把扩展函数放在了函数这一块。 
还在为了给类扩展一个方法而写多一个子类吗?好吧,再也不用这么做了,让kotlin 扩展函数来帮你解决。下面直接用一个例子说明。

<code class="language-kotlin hljs javascript has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;">    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 扩展函数是用类名.函数名来定义的,</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 扩展后该类的所有实例都能够使用该函数</span>    fun <T> MutableList<T>.swap(index1: Int, index2: Int) {  val tmp = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>[index1] <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 'this' corresponds to the list</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>[index1] = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>[index2]  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>[index2] = tmp}<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 函数调用</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">var</span> l = MutableList<<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span>>()l.swap(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>

这里为什么叫函数而不是方法呢? 
首先要知道方法和函数的区别:其实没有实质上的区别,只不过当一个函数放在类或类实例中时称为方法(也就是面向对象语言的说法),而函数与类不相关(面向过程)。 
可以猜出,这里的扩展函数并不是真正地在类中增加一个方法,从kotlin文档中也可以知道:

Extensions are resolved statically

Extensions do not actually modify classes they extend. By defining an extension, you do not insert new members into a class, but merely make new functions callable with the dot-notation on instances of this class.

We would like to emphasize that extension functions are dispatched statically, i.e. they are not virtual by receiver type. This means that the extension function being called is determined by the type of the expression on which the function is invoked, not by the type of the result of evaluating that expression at runtime. For example:

也就是说,扩展函数是静态加载的,与类或实例无关。 
这里摘kotlin文档上的一个例子:

<code class="language-kotlin hljs mathematica has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;">open class <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">C</span>class <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">D</span>: <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">C</span>()fun <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">C</span>.foo() = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"c"</span>fun <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">D</span>.foo() = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"d"</span>fun printFoo(c: <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">C</span>) <span class="hljs-list" style="box-sizing: border-box;">{    println(c.foo())}</span>printFoo(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">D</span>())    // 结果是 c</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>

因为默认函数却决于调用时声明的类型,而不是运行时计算出来的结果。

  • 成员函数优先于扩展函数 
    再来一个官方文档的例子:

    <code class="language-kotlin hljs scss has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;">    class C{        fun <span class="hljs-function" style="box-sizing: border-box;">foo()</span>{ <span class="hljs-function" style="box-sizing: border-box;">println(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"member"</span>)</span> }    }     fun C<span class="hljs-class" style="box-sizing: border-box;">.foo</span>(){ <span class="hljs-function" style="box-sizing: border-box;">println(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"extension"</span>)</span> }    <span class="hljs-function" style="box-sizing: border-box;">C()</span><span class="hljs-class" style="box-sizing: border-box;">.foo</span>()    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 结果是member</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

    扩展属性和扩展函数定义,使用和性质都基本一样,就不细说了


0 0