面向对象

声明类

Kotlin使用关键字class声明类:

class A {
    // ....
}

// 如果是一个空的类,可以省略大括号
class B

构造函数

在 Kotlin 中的一个类可以有一个主构造函数以及一个或多个次构造函数。

主构造函数

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

    class Person constructor(firstName: String) {}
  2. 如果主构造函数没有任何注解或者可见性修饰符,可以省略这个 constructor 关键字:

    class Person(firstName: String) {
    }
  3. 如果构造函数有注解或可见性修饰符,这个 constructor 关键字是必需的,并且这些修饰符在它前面:

    class Customer public @Inject constructor(name: String) { /*……*/ }
  4. 主构造函数不能包含任何代码,他只有一对括号,以及构造所需的参数声明,如果要在构造对象时进行初始化,可以使用 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}")
        }
    }
    
    // First property: hello
    // First initializer block that prints hello
    // Second property: 5
    // Second initializer block that prints 5
  5. 主构造的参数可以在初始化块中使用。它们也可以在类体内声明的属性初始化器中使用:

    class Customer(name: String) {
        val customerKey = name.toUpperCase()
    }
  6. 主构造函数的参数可以使用 varval类型,但是不能有const val常量:

    class Person(
        val firstName: String,
        val lastName: String,
        var age: Int, // trailing comma
    ) {
        // ...  
    }
  7. 如果非抽象类没有声明任何(主或次)构造函数,它会有一个生成的不带参数的主构造函数,并且他的访问修饰符是public的

    class Person(firstName: String) {
    }
    // 等同于
    class Person public constructor (firstName: String) {
    }
  8. 主构造器上的所有参数是可以设置默认值的:

    class Customer(val customerName: String = "")
  9. 如果主构造器上的所有参数都有默认值,编译器会生成 一个额外的无参构造器,它将使用默认值。这使得 Kotlin 更易于使用像 Jackson 或者 JPA 这样的通过无参构造函数创建类的实例的库。

次构造函数

  1. 不在类头,在类内部使用constructor关键字声明次构造函数

     class Person {
         var children: MutableList<Person> = mutableListOf()
         constructor(parent: Person) {
             parent.children.add(this)
         }
     }
  2. 如果类有一个主构造函数,每个次构造函数需要委托给主构造函数, 可以直接委托或者通过别的次构造函数间接委托。委托到同一个类的另一个构造函数用 this 关键字即可:

    class Person(val name: String) {
        var children: MutableList<Person> = mutableListOf()
    
        // 定义了一个次构造器,将name委托给主构造器
        // 创建对象时,次构造器中的内容会先执行主构造器,主构造器的代码包含init中的代码
        // 这里很像Java的构造器,调用this(xx)时,必须放在构造器的开头
        constructor(name: String, parent: Person) : this(name) {
            parent.children.add(this)
        }
    }
  3. 同样的,一个次构造器,也是可以给默认值的

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

创建类实例

Kotlin中没有new关键字,通过直接调用构造函数即可创建类实例:

val invoice = Invoice()

val customer = Customer("Joe Smith")

最后更新于