Kotlin之类与继承
[TOC]
Kotlin 中使用关键字 class 声明类
1 | class ClassName { ... } |
类声明由类名、类头(指定其类型参数、主构造函数等)以及由花括号包围的类体构成。类头与类体都是可选的; 如果一个类没有类体,可以省略花括号。
1 | class Empty |
构造函数
在 Kotlin 中的一个类可以有一个主构造函数以及一个或多个次构造函数。主构造函数是类头的一部分:它跟在类名(与可选的类型参数)后,使用constructor修饰。
1 | class Person constructor(firstName: String) { ... } |
如果主构造函数没有任何注解或者可见性修饰符,可以省略这个 constructor 关键字。
1 | class Person(firstName: String) { ... } |
主构造函数不能包含任何的代码。初始化的代码可以放到以 init 关键字作为前缀的初始化块(initializer blocks)中。
在实例初始化期间,初始化块按照它们出现在类体中的顺序执行,与属性初始化器交织在一起:
1 | class InitOrderDemo(name: String) { |
请注意,主构造的参数可以在初始化块中使用。它们也可以在类体内声明的属性初始化器中使用:
1 | class Customer(name: String) { |
事实上,声明属性以及从主构造函数初始化属性,Kotlin 有简洁的语法:
1 | class Person(val firstName: String, val lastName: String, var age: Int) { …… } |
与普通属性一样,主构造函数中声明的属性可以是可变的(var)或只读的(val)。
如果构造函数有注解或可见性修饰符,这个 constructor 关键字是必需的,并且这些修饰符在它前面:
1 | class Customer public @Inject constructor(name: String) { …… } |
更多详情,参见可见性修饰符
次构造函数
类也可以声明前缀有 constructor的次构造函数:
1 | class Person { |
如果类有一个主构造函数,每个次构造函数需要委托给主构造函数, 可以直接委托或者通过别的次构造函数间接委托。委托到同一个类的另一个构造函数用 this 关键字即可:
1 | class Person(val name: String) { |
请注意,初始化块中的代码实际上会成为主构造函数的一部分。委托给主构造函数会作为次构造函数的第一条语句,因此所有初始化块中的代码都会在次构造函数体之前执行。即使该类没有主构造函数,这种委托仍会隐式发生,并且仍会执行初始化块:
1 | class Constructors { |
如果一个非抽象类没有声明任何(主或次)构造函数,它会有一个生成的不带参数的主构造函数。构造函数的可见性是 public。如果你不希望你的类有一个公有构造函数,你需要声明一个带有非默认可见性的空的主构造函数:
1 | class DontCreateMe private constructor () { ... } |
注意:在 JVM 上,如果主构造函数的所有的参数都有默认值,编译器会生成 一个额外的无参构造函数,它将使用默认值。这使得 Kotlin 更易于使用像 Jackson 或者 JPA 这样的通过无参构造函数创建类的实例的库。
1 | class Customer(val customerName: String = "") |
创建类的实例
要创建一个类的实例,我们就像普通函数一样调用构造函数:
1 | val invoice = Invoice() |
注意 Kotlin 并没有 new 关键字。
创建嵌套类、内部类与匿名内部类的类实例在嵌套类中有述。