创建类
您不仅可以使用预定义的类型如
IntRange
和String
,还可以创建自己的对象类型。
事实上,在面向对象编程中,创建新类型是其中的主要活动。您可以通过定义类来创建新类型的对象。
对象是解决问题的一部分。首先,将对象视为表达概念。作为第一个近似值,如果在问题中发现一个“事物”,则在解决方案中将该事物表示为对象。
假设您想要创建一个程序来管理动物园中的动物。基于它们的行为、需求、与其他动物相处的方式以及与其他动物争斗的方式,对不同类型的动物进行分类是有意义的。每种动物的特定之处都包含在该动物对象的分类中。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,大小写不限)开头,但可以包括数字和下划线等内容。按照惯例,我们将类名的第一个字母大写,并将所有 val
和 var
的第一个字母小写。
Animals.kt
首先定义了三个新类,然后创建了这些类的四个对象(也称为实例)。
Giraffe
是一个类,但生活在博茨瓦纳的特定五岁雄性长颈鹿是一个对象。每个对象与其他所有对象都不同,因此我们给它们命名为 g1
和 g2
。
注意最后四行输出的相当神秘。@
之前的部分是类名,@
之后的数字是对象在计算机内存中的位置。是的,尽管其中包含一些字母,但它是一个数字,被称为“十六进制表示法”。您程序中的每个对象都有自己独特的地址。
在这里定义的类(Giraffe
、Bear
和 Hippo
)尽可能简单:整个类定义只有一行。更复杂的类使用大括号({
和 }
)来创建包含该类特性和行为的类体。
在类内部定义的函数属于该类。在 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 找到。