前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【读书笔记】《Kotlin in Action》学习笔记(上)

【读书笔记】《Kotlin in Action》学习笔记(上)

作者头像
IT自学不成才
发布2019-01-07 11:22:27
7680
发布2019-01-07 11:22:27
举报
文章被收录于专栏:Godot游戏开发引擎介绍和入门

【读书笔记】《Kotlin in Action》学习笔记(上)

2017-09-16 by Liuqingwen | Tags: Kotlin | Hits

一、前言

写这篇文章的时候心里真的有一万个草泥马在我心中奔腾而过,简要说明三点:

  1. 最近太忙了,给学生补课占据了自己不少时间,已经有一个多月没有认真写文章,写代码了!
  2. 我这次利用周末时间写的这个主题分两部分,其实太长的文章也不适合阅读,虽然偷了点懒但也是有道理的。
  3. 我第一次边看 PDF 电子书边做笔记,受益匪浅,我建议每一位同志都应该这样做。

另外,我的读书笔记是在一本网上下载的 PDF 书:《 Kotlin in Action 》上做的,质量不怎么好,不过后来通过 mobilehub 的微信赠书活动有幸免费获得了一本中文版 《 Kotlin 实战》,目前还没有时间看,我想自己看完后还会增加一些其他的基础知识点,作为自己随时查阅的资料和大家一起学习探讨的话题吧。

二、笔记

1、 Kotlin中的“内部的类”默认为“非内部类”

也就是说,写在某个父类内部的子类是不能直接访问这个父类的属性和方法的,有别于 Java 中的内部类!在 Kotlin 中如果我们需要写内部类的话,一定要使用 inner 关键字!

代码语言:javascript
复制
//nested classes aren't inner by default
class OuterClass {
    private val outerProperty = "outer"
    private val innerClass1 = OuterClass.InnerClass1()   //ok
    //private val innerClass2 = OuterClass.InnerClass2() //compile error
    
    class InnerClass1 {
        //fun reachToOuterClass() = outerProperty //compile error
    }
    
    inner class InnerClass2 {
        fun reachToOuterClass() = outerProperty //ok
    }
}

2、 Kotlin中的数据类不会自动处理非首要构造函数中的属性

有时候我们在使用 data class 的时候也需要使用其他方法或者其他计算出来的属性(比如类似 swift 中的 computed property 之类),这个时候这个属性就没必要定义在 primary constructor 构造函数中,而是定义在类里面( secondary constructor ),这时候 Kotlin 中的数据类只会自动计算定义在 primary constructor 中的属性的 hashCode()equals() 方法,而其他的不会。

代码语言:javascript
复制
//properties that aren’t declared in the primary constructor 
//don’t take part in the equality checks and hashcode calculation
data class DataClass(val primaryProp:String = "[primary_constructor_property]") {
    val secondaryProp:String = "[secondary_constructor_property]"
}

fun main(vararg parameters:String) {
    val data = DataClass()
    println(data) //print: DataClass(primaryProp=[primary_constructor_property])
}

这一点我在使用安卓 Room 数据库的时候遇到过,所以有时候我们还是有必要自己动手在 data class 中重写 toString() 这些方法的。 :joy

3、 Kotlin中的companion object可以实现接口

这点对我来说,真的非常怪异!我目前还从未使用过,在之后开发过程中引起注意,希望自己能够弄懂这一点!一直认为 companion object 就像 Java 中静态方法一样,没任何区别,但是它居然还能实现 interface 接口,有点不可思议啊!下面的代码来自官方例子的修改,大家可以研究一下:

代码语言:javascript
复制
//A companion object can implement interfaces
interface JSONFactory<out T> {
    fun fromJSON(jsonText:String):T
}

class Person(val name:String) {
    companion object:JSONFactory<Person> {
        override fun fromJSON(jsonText:String):Person = Person("Kotlin")
    }
}

fun <T> loadFromJSON(factory:JSONFactory<T>, jsonText:String):T = factory.fromJSON(jsonText)

fun main(vararg parameters:String) {
    loadFromJSON(Person, """{name:"kotlin"}""")
}

4、 传入lambda和传入object的一个区别

在 Koltlin 中 SAM(Single Abstract Method) 参数我们一般传入的是 lambda 表达式,简洁实用,而且 lambda 作为最后一个参数还可以放小括号后面,和 swift 一样方便。当然,我们也可以采用和 Java 一样的方式:使用 object 实现 SAM 接口,但是这样做的话,可能会在每次调用函数的时候都会创建一个新的 object 实例。参考下面的代码,来自官方的例子。

下面是 Java 中的代码,为了使用 Runnable 作为 lambda 参数:

代码语言:javascript
复制
public class TheJavaClass {
    public static void postponeComputation(int delay, Runnable computation) throws InterruptedException {
        System.out.println(computation);
    }
}

下面是 Kotlin 中测试代码,注意,使用 object 可以通过设置为成员属性变量的方式避免每次实例化,而使用 lambda 时如果引用了成员属性那么会变成和 object 方式一样每次调用都会创建实例!(注释后面为输出的数据地址,结果每次都会不同):

代码语言:javascript
复制
//When you explicitly declare an object, a new instance is created on each invocation
//If the lambda captures variables from the surrounding scope, it’s no longer possible to
//reuse the same instance for every invocation
class Test {
    var localProperty = "Local"
    val runnableObj = object : Runnable {
        override fun run() { }
    }
    
    fun testObject() = TheJavaClass.postponeComputation(1000, object : Runnable {
        override fun run() { }
    })
    fun testObjectWithNamed() = TheJavaClass.postponeComputation(1000, runnableObj)
    fun testLambda() = TheJavaClass.postponeComputation(1000) { }
    fun testLambdaWithRef() = TheJavaClass.postponeComputation(1000) { localProperty = "Local_m" }
}

fun main(vararg parameters:String) {
    val test = Test()
    test.testObject() //@2626b418
    test.testObject() //@5a07e868
    
    test.testLambda() //@76ed5528
    test.testLambda() //@76ed5528
    
    test.testObjectWithNamed() //@2c7b84de
    test.testObjectWithNamed() //@2c7b84de
    
    test.testLambdaWithRef() //@3fee733d
    test.testLambdaWithRef() //@5acf9800
}

5、 Kotlin中的类型参数(T)不加?标记也能为空

嗯,唯一一个 Kotlin 中的特例:不需要在类型参数( Type Parameter )后面加 ? 可空标记它就能用于 null 空值!这是使用 Kotlin 的时候需要注意的。下面是官方的例子,一眼就能看明白。

代码语言:javascript
复制
//A type parameter can be substituted for any type, including a nullable type
//Note that type parameters are the [only] exception to the rule
fun <T> printAnythingHashCode(t: T) {
    println(t?.hashCode()) //"T" is inferred as "Any?"
}
fun <T> printNullableHashCode(t: T?) {
    println(t?.hashCode())
}

fun main(vararg parameters:String) {
    printNullableHashCode(null) //this is fine
    printAnythingHashCode(null) //it works fine too
}

三、未完待续……

Kotlin


Comments:

Please enable JavaScript to view the comments powered by Disqus.

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-09-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 【读书笔记】《Kotlin in Action》学习笔记(上)
    • 一、前言
      • 二、笔记
        • 三、未完待续……
          • Comments:
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档