本文是对<<Kotlin in Action>>
的学习笔记,若是须要运行相应的代码能够访问在线环境 try.kotlinlang.org,这部分的思惟导图为: 框架
在平时的开发中,咱们每每会使用许多的xxBean
对象用做数据容器,而在定义这些对象时,通常会重写它的如下三个方法:函数
equals
:用来比较实例hashCode
:用来做为例如HashMap
这种基于哈希容器的类toString
:用来为类生成按声明顺序排列的全部字段的字符串表达形式在Kotlin
中,只须要为你的类添加data
关键字,以上这些必要的方法就会自动生成好,例以下面的例子,咱们演示了以上三个方法的做用: 学习
equals
和hashCode
方法会将全部在主构造方法中声明的属性归入考虑:设计
equals
方法会检测全部的属性的值是否相等hashCode
方法会返回一个根据全部属性生成的哈希值在设计数据类时,应当尽可能只使用只读的属性,让数据类的实例不可变,由于若是不这样,被用做键的对象在加入HashMap
或者相似容器后被修改了,容器会进入一种无效的状态。3d
为了让使用不可变对象变得容易,Kotlin
编译器为它们生成了copy
方法,并在copy
的同时修改某些属性的值,copy
出来的副本有着单独的声明周期并且不会影响代码中引用原始实例的位置,使用方法以下: code
当咱们须要向一个类添加一些行为时,通常有两种作法:cdn
而Kotlin
将委托做为一个语言级别的功能作了头等支持。不管何时实现一个接口,你均可以使用by
关键字 将接口的实现委托到另外一个对象;当须要修改某些方法的行为时,能够重写它们,这样你的方法就会被调用而不是使用生成的方法,能够保留感到满意的委托给内部的实例中的默认实现。 对象
object
关键字在多种状况下出现,它的核心理念为:这个关键字 定义一个类并同时建立一个实例,下面咱们介绍它的三个应用场景:blog
Java
的匿名内部类。在Java
中,单例模式一般是使用private
构造方法,而且用静态字段来持有这个类仅有的实例。继承
而在Kotlin
中,经过使用对象声明功能,将类声明与该类的单一实例声明结合到了一块儿。
object
关键字引入,一个对象声明能够很是高效地以一句话来定义一个类和一个该类的变量。.
字符的方式来调用方法和访问属性。对象声明能够继承自类和接口,这一般在你使用的框架须要去实现一个接口,可是你的实现不包含任何状态的时候颇有用。
在类中使用对象声明时,这样的对象一样只有一个单一实例:它们在每一个容器类的实例中具备相同的实例。
若是要在Java
中使用Kotlin
中的声明对象,能够经过访问静态的INSTANCE
字段:
Kotlin
的类不能拥有静态成员,做为替代,Kotlin
依赖包级别函数(在大多数情形下可以替代Java
的静态方法)和对象声明(在其余状况下替代Java
的静态方法,同时还包括静态字段),在大多数状况下,推荐使用顶层函数,可是顶层函数不能访问类的private
变量。
所以,若是你须要写一个 在没有类实例的状况下 调用可是须要 访问类内部的函数,能够将其写成那个类中的 对象声明的成员。
在类中定义的对象之一可使用一个特殊的关键字来标记 companion,若是这样作,就得到了直接 经过容器类名称来访问这个对象的方法和属性的能力,再也不须要显示地指明对象的名称,下面是一个基础的示例:
下面是使用伴生对象来实现工厂方法的例子:
伴生对象是一个声明在类中的普通对象,它能够有名字,实现一个接口或者有扩展函数或属性。假设咱们须要在对象和JSON
之间进行序列化和反序列化,能够将序列化的逻辑放在伴生对象中。
Person
类)来引用伴生对象,因此没必要关心它的名字,若是省略了伴生对象的名字,默认的名字将会分配为
Companion
。
就像其它对象声明同样,伴生对象也能够实现接口,能够将包含它的类的名字当作实现了该接口的对象实例来使用。
在 Kotlin 知识梳理(2) - 函数的定义与调用 中,咱们介绍了经过扩展函数,能够经过代码库中其它地方定义类实例调用的方法,可是若是你须要定义能够经过 类自身调用的方法,就像伴生对象方法或者Java
静态方法该怎么办呢?
举例来讲,若是类有一个伴生对象,能够经过在其上定义扩展函数来作到这一点,即类C
有一个伴生对象,而且在C.Companion
上定义了一个扩展函数func
,则能够经过C.fun()
来调用它。
下面,咱们为Person
类的伴生对象定义一个扩展函数:
当调用toJson
就像是它是一个伴生对象定义的方法同样,可是实际上它是做为扩展函数在外部定义的。而为了可以为你的类定义扩展,必须在其中声明一个对象,即便是空的。
object
关键字不只可以用来代表单例式的对象,还能用来声明 匿名对象,它替代了Java
中匿名内部类的用法。例如,让咱们来看看怎样将一个典型的匿名内部类用法转换成Kotlin
:
除了去掉对象的名字外,语法与对象声明相同的。对象表达式声明了一个类并建立了该类的一个实例,可是没有给这个类或是实例分配一个名字。一般来讲,它们都是不须要名字的,由于你会将这个对象用做一个函数调用的参数。若是你须要给对象分配一个名字,能够将其存储到一个变量中:
Java
的匿名类同样,在对象表达式中的代码能够访问建立它的函数中的变量,可是与Java
不一样,访问并被限制在final
变量,还能够在对象表达式中修改变量的值。