类声明
Kotlin 中用 class
关键字声明一个类, 跟 java 有区别的一些地方是, 你可以在同个
源文件中声明多个 public
类; 如果一个类没有 body, 那个花括号是可以省略的(比如
spring boot 中的启动类, 只是用来放注解 @SpringBootApplication
);
@SpringBootApplication
class KotlinClassApplication
构造函数
在 Kotlin 中的一个类可以有一个主构造函数以及一个或多个次构造函数。主构造函数是
类头的一部分.
// 主构造函数中不加 var, val, 那么 name 和 age 只是构造函数的参数而已
class Animal constructor(name: String, age:Int?)
注意, 如果构造函数参数不加 val
或 var
, kotlin 编译器不会将他们当成类属性, 即
不会自动生成 getter setter 方法. 所以一般都要加上 val
.
// 如果不加 var, val
// 需要再写一下属性初始化代码才行
class Dog (name: String, age: Int?) {
val name = name
val age = age
// 属性必须初始化, 除非使用 lateinit var 标记为延迟初始化的属性
lateinit var owner: String
}
如果属性不写在主构造函数中, 那就必须初始化; 除非加上 lateinit var
标记
新建一个对象不需要使用 new
关键字, 直接调用构造函数就可以了.
@Test fun testConstruct() {
val person = Person("codergege", null)
assertEquals("codergege", person.name)
assertNull(person.age)
}
可以看到, 虽然我们并没有写 getter setter 方法, 但是已经可访问属性了, 因为 kotlin
编译器已经自动为我们生成.
如果主构造函数没有任何注解或者可见性修饰符 constructor
关键字可以省略.
class Person(val name: String, val age: Int?)
如果需要在构造函数中写点逻辑, 得用 init
块. 例如:
class Person(val name: String, val age: Int?) {
init {
require(name.trim().length > 0) {
"名称长度必须大于 0 !"
}
if(age != null) {
require(age > 0 && age < 150) {
"年龄必须是 (0, 150) 之间"
}
}
}
}
一个对象的初始化过程里, 多个 init
块和属性初始化代码是按代码顺序执行的
class InitOrderDemo(name: String) {
val firstProperty = "First property: $name".also(::println)
init {
println("First initializer block that prints ${name}")
}
val secondProperty = "Second property: ${name.length}".also(::println)
init {
println("Second initializer block that prints ${name.length}")
}
}
"xxx".also()
会将调用传入的函数, 参数是 this
(谁调就传谁) 并返回 this
测试这段代码:
@Test fun testInitOrder() {
val obj = InitOrderDemo("hello")
}
输出是
First property: hello
First initializer block that prints hello
Second property: 5
Second initializer block that prints 5
注意到, name
这个构造函数的参数也能被用来给属性赋值.这是因为编译器最终会将所
有的 init
和属性初始化代码放进主构造函数中.
次构造函数
次构造函数通过 constructor
声明.
次构造函数(Secondary Constructor)必须通过 this
调用主构造函数, 然后把参数传过去:
当然, 如果没有主构造函数, 也可以用 this
调用其他次构造函数.
// 非主构造函数中, 参数不允许有 val 和 var, 就像普通函数那样.
constructor(name: String): this(name, null)
现在通过第二个构造函数创建一个对象:
val jack = Person("Jack")
assertEquals("Jack", jack.name)
assertNull(jack.age)
Kotlin 中所有默认访问级别是 public
的.
如果一个类的主构造函数中所有的属性都有默认值, 那么编译器会自动再生成一个无参
的构造函数, 方便在 Spring, JPA 等框架中使用.
以前是需要加上 no-arg 插件的, 现在这个插件不是必须的了.
网友评论