类的声明

Kotlin 中使用关键字 class 声明类,默认是public的

class Invoice { /*……*/ }

类声明由类名、类头(指定其类型参数、主构造函数等)以及由花括号包围的类体构成。类头与类体都是可选的; 如果一个类没有类体,可以省略花括号。

class Empty

构造函数

在 Kotlin 中的一个类可以有一个主构造函数以及一个或多个次构造函数。构造函数就是类的实例化的时候,需要调用的方法。

主构造函数

主构造函数是类头的一部分:它跟在类名(与可选的类型参数)后。

class Person constructor(var age: Int, var name: String) { /*……*/ }

如果主构造函数没有任何注解或者可见性修饰符,可以省略这个 constructor 关键字。

class Person(var age: Int, var name: String) { /*……*/ }

主构造函数不能包含任何的代码。初始化的代码可以放到以 init 关键字作为前缀的初始化块(initializer blocks)中。

在实例初始化期间,初始化块按照它们出现在类体中的顺序执行,与属性初始化器交织在一起:

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}")
    }
}

/*
First property: hello
First initializer block that prints hello
Second property: 5
Second initializer block that prints 5
*/

注意,主构造的参数可以在初始化块中使用。它们也可以在类体内声明的属性初始化器中使用:

class Customer(name: String) {
    val customerKey = name.toUpperCase()
}

事实上,声明属性以及从主构造函数初始化属性,Kotlin 有简洁的语法:

class Person(val firstName: String, val lastName: String, var age: Int) { /*……*/ }

与普通属性一样,主构造函数中声明的属性可以是可变的(var)或只读的(val)。

如果构造函数有注解或可见性修饰符,这个 constructor 关键字是必需的,并且这些修饰符在它前面:

class Customer public @Inject constructor(name: String) { /*……*/ }

次构造函数

类也可以声明前缀有 constructor次构造函数

class Person {
    var children: MutableList<Person> = mutableListOf()
    constructor(parent: Person) {
        parent.children.add(this)
    }
}

如果类有一个主构造函数,每个次构造函数需要委托给主构造函数(也就是说每个次构造器都需要调用主构造器)。

可以直接委托或者通过别的次构造函数间接委托。委托到同一个类的另一个构造函数用 this 关键字即可:

class Person(val name: String) {
    var children: MutableList<Person> = mutableListOf()
    constructor(name: String, parent: Person) : this(name) {
        parent.children.add(this)
    }
}

初始化块中的代码实际上会成为主构造函数的一部分。委托给主构造函数会作为次构造函数的第一条语句,因此所有初始化块与属性初始化器中的代码都会在次构造函数体之前执行。即使该类没有主构造函数,这种委托仍会隐式发生,并且仍会执行初始化块:

class Constructors {
    init {
        println("Init block")
    }

    constructor(i: Int) {
        println("Constructor")
    }
}

/*
Init block
Constructor
*/

如果一个非抽象类没有声明任何(主或次)构造函数,它会有一个生成的不带参数的主构造函数。构造函数的可见性是 public。如果你不希望你的类有一个公有构造函数,你需要声明一个带有非默认可见性的空的主构造函数:

class DontCreateMe private constructor () { /*……*/ }

在 JVM 上,如果主构造函数的所有的参数都有默认值,编译器会生成 一个额外的无参构造函数,它将使用默认值。这使得 Kotlin 更易于使用像 Jackson 或者 JPA 这样的通过无参构造函数创建类的实例的库。

class Customer(val customerName: String = "")

创建类的实例

注意 Kotlin 并没有 new 关键字

要创建一个类的实例,我们就像普通函数一样调用构造函数:

val invoice = Invoice()

val customer = Customer("Joe Smith")
class Person(val age: Int, val name: String) {}


val person = Person(18, "jacob")

类的属性

属性的声明

Kotlin 类中的属性既可以用关键字 var 声明为可变的,也可以用关键字 val 声明为只读的。

在Kotlin中,定义一个属性,必须初始化。(下面代码中的属性不需要构造器传递参数进行初始化,是在类的内部初始化了固定的值)

class Address {
    var name: String = "Holmes, Sherlock"
    var street: String = "Baker"
    var city: String = "London"
    var state: String? = null
    var zip: String = "123456"
}

通过构造函数传递的参数也是属于这个类的属性

class Person(val age: Int, val name: String) {}


val person = Person(18, "jacob")

属性的使用

要使用一个属性,只要用名称引用它即可:

class Person(val age: Int, val name: String) {
    var street: String = "Baker"
    var city: String = "London"
}

想要调用上面类中的属性,首先需要实例化这个类的对象

val person = Person(18, "jacob")
var age = person.age

Getters 与 Setters

属性:Getters、Setters、const、lateinit - Kotlin 语言中文站

抽象类

类以及其中的某些成员可以声明为 abstract。抽象成员在本类中可以不用实现。

抽象类中的方法默认不可以被复写,如果需要复写需要使用关键字open声明

abstract class AbsClass {
    abstract fun absMethod()
    open fun overridable() {}
    fun onOverridable() {} 
}

需要注意的是,我们并不需要用 open 标注一个抽象类或者函数——因为这不言而喻。

我们可以用一个抽象成员覆盖一个非抽象的开放成员

open class Polygon {
    open fun draw() {}
}

abstract class Rectangle : Polygon() {
    abstract override fun draw()
}

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐