Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

对象

object 关键字定义了类似类的东西。然而,您不能创建 object 的实例,它只有一个实例。这有时被称为单例模式。

object 是将逻辑上属于一起的函数和属性组合在一起的一种方式,但此组合不需要多个实例,或者您想明确阻止多个实例。您永远不会创建 object 的实例,因为只有一个实例,并且在定义 object 后可以使用它:

// Objects/ObjectKeyword.kt
package objects
import atomictest.eq

object JustOne {
  val n = 2
  fun f() = n * 10
  fun g() = this.n * 20   // [1]
}

fun main() {
  // val x = JustOne() // Error
  JustOne.n eq 2
  JustOne.f() eq 20
  JustOne.g() eq 40
}

在这里,您不能使用 JustOne() 来创建类 JustOne 的新实例。这是因为 object 关键字定义了结构并同时创建了对象。此外,它将元素放置在 object 的命名空间内。如果您只想让 object 在当前文件中可见,您可以将其设置为 private

  • [1] 关键字 this 指的是单个对象实例。

您不能为 object 提供参数列表。

在使用 object 时,命名约定略有不同。通常情况下,当我们创建一个类的实例时,我们会将实例名称的第一个字母小写。然而,在创建 object 时,Kotlin 定义类并同时创建该类的单个实例。因此,我们将 object 的名称的第一个字母大写,因为它还表示一个类。

object 可以继承普通类或接口:

// Objects/ObjectInheritance.kt
package objects
import atomictest.eq

open class Paint(val color: String) {
  open fun apply() = "Applying $color"
}

object Acrylic: Paint("Blue") {
  override fun apply() =
    "Acrylic, ${super.apply()}"
}

interface PaintPreparation {
  fun prepare(): String
}

object Prepare: PaintPreparation {
  override fun prepare() = "Scrape"
}

fun main() {
  Prepare.prepare() eq "Scrape"
  Paint("Green").apply() eq "Applying Green"
  Acrylic.apply() eq "Acrylic, Applying Blue"
}

只有一个 object 实例,因此该实例在使用它的所有代码之间共享。这里是一个位于自己的 package 中的 object

// Objects/GlobalSharing.kt
package objectsharing

object Shared {
  var i: Int = 0
}

现在,我们可以在不同的包中使用 Shared

// Objects/Share1.kt
package objectshare1
import objectsharing.Shared

fun f() {
  Shared.i += 5
}

还可以在第三个包中使用:

// Objects/Share2.kt
package objectshare2
import objectsharing.Shared
import objectshare1.f
import atomictest.eq

fun g() {
  Shared.i += 7
}

fun main() {
  f()
  g()
  Shared.i eq 12
}

您可以从结果中看到 Shared 在所有包中都是相同的对象,这是因为 object 创建一个单一的实例。如果将 Shared 设置为 private,它在其他文件中将不可用。

object 不能放在函数内部,但它们可以嵌套在其他 object 或类内部(前提是这些类本身不是在其他类内部嵌套的):

// Objects/ObjectNesting.kt
package objects
import atomictest.eq

object Outer {
  object Nested {
    val a = "Outer.Nested.a"
  }
}

class HasObject {
  object Nested {
    val a = "HasObject.Nested.a"
  }
}

fun main() {
  Outer.Nested.a eq "Outer.Nested.a"
  HasObject.Nested.a eq "HasObject.Nested.a"
}

还有一种将 object 放在类内部的方法:companion object,您将在 伴生对象 部分中看到。

练习和解决方案可以在 www.AtomicKotlin.com 上找到。