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

创建类

您不仅可以使用预定义的类型如 IntRangeString,还可以创建自己的对象类型。

事实上,在面向对象编程中,创建新类型是其中的主要活动。您可以通过定义来创建新类型的对象。

对象是解决问题的一部分。首先,将对象视为表达概念。作为第一个近似值,如果在问题中发现一个“事物”,则在解决方案中将该事物表示为对象。

假设您想要创建一个程序来管理动物园中的动物。基于它们的行为、需求、与其他动物相处的方式以及与其他动物争斗的方式,对不同类型的动物进行分类是有意义的。每种动物的特定之处都包含在该动物对象的分类中。Kotlin 使用 class 关键字来创建新类型的对象:

// CreatingClasses/Animals.kt

// 创建一些类:
class Giraffe
class Bear
class Hippo

fun main() {
  // 创建一些对象:
  val g1 = Giraffe()
  val g2 = Giraffe()
  val b = Bear()
  val h = Hippo()

  // 每个对象都是独特的:
  println(g1)
  println(g2)
  println(h)
  println(b)
}
/* 输出:
Giraffe@28d93b30
Giraffe@1b6d3586
Hippo@4554617c
Bear@74a14482
*/

要定义一个类,从 class 关键字开始,然后是新类的标识符。类名必须以字母(A-Z,大小写不限)开头,但可以包括数字和下划线等内容。按照惯例,我们将类名的第一个字母大写,并将所有 valvar 的第一个字母小写。

Animals.kt 首先定义了三个新类,然后创建了这些类的四个对象(也称为实例)。

Giraffe 是一个类,但生活在博茨瓦纳的特定五岁雄性长颈鹿是一个对象。每个对象与其他所有对象都不同,因此我们给它们命名为 g1g2

注意最后四行输出的相当神秘。@ 之前的部分是类名,@ 之后的数字是对象在计算机内存中的位置。是的,尽管其中包含一些字母,但它是一个数字,被称为“十六进制表示法”。您程序中的每个对象都有自己独特的地址。

在这里定义的类(GiraffeBearHippo)尽可能简单:整个类定义只有一行。更复杂的类使用大括号({})来创建包含该类特性和行为的类体

在类内部定义的函数属于该类。在 Kotlin 中,我们称这些为类的成员函数。一些面向对象的语言(如 Java)选择将它们称为方法,这个术语来自早期的面向对象语言(如 Smalltalk)。为了强调 Kotlin 的函数性质,设计者选择舍弃了术语方法,因为一些初学者发现这种区分令人困惑。相反,整个语言中都使用术语函数

如果不会引起歧义,我们将只说“函数”。如果必须进行区分:

  • 成员函数属于类。
  • 顶层函数独立存在,不属于任何类。

这里,bark() 属于 Dog 类:

// CreatingClasses/Dog.kt

class Dog {
  fun bark() = "yip!"
}

fun main() {
  val dog = Dog()
}

main() 中,我们创建了一个 Dog 对象,并将其赋值给 val dog。Kotlin 发出了一个警告,因为我们从未使用过 dog

成员函数使用对象名调用(调用),后面跟一个 .(点号),然后是函数名和参数列表。在这里,我们调用 meow() 函数并显示结果:

// CreatingClasses/Cat.kt

class Cat {
  fun meow() = "mrrrow!"
}

fun main() {
  val cat = Cat()
  // 为 'cat' 调用 'meow()':
  val m1 = cat.meow()
  println(m1)
}
/* 输出:
mrrrow!
*/

成员函数作用于类的特定实例。在调用 meow() 时,必须使用对象调用它。在调用过程中,meow() 可以访问该对象的其他成员。

在调用成员函数时,Kotlin 通过在内部传递一个引用来跟踪感兴趣的对象。这个引用在成员函数内部可以通过关键字 this 使用。

成员函数可以通过命名这些元素来特殊访问类内的其他元素。您还可以使用 this 显式地限定对这些元素的访问。在这里,exercise() 通过使用和不使用限定调用 speak()

// CreatingClasses/Hamster.kt

class Hamster {
  fun speak() = "Squeak! "
  fun exercise() =
    this.speak() +   // 使用 'this' 限定
      speak() +      // 不使用 'this'
      "Running on wheel"
}

fun main() {
  val hamster = Hamster()
  println(hamster.exercise())
}
/* 输出:
Squeak! Squeak! Running on wheel
*/

exercise() 中,我们首先使用显式的 this 调用 speak(),然后省略了限定。

有时您会看到包含不必要显式 this 的代码。那种代码通常来自于知道另一种语言的程序员,其中 this 要么是必需的,要么是其风格的一部分。不必要地使用一个特性会让读者困惑,他们会花时间来弄清楚您为什么这么做。我们建议避免不必要地使用 this

在类外部,您必须使用 hamster.exercise()hamster.speak()

练习和解答可以在 www.AtomicKotlin.com 找到。