Kotlin 类
最后修改于 2024 年 1 月 29 日
本文介绍了如何在 Kotlin 语言中使用类。类是 Kotlin 中对象的蓝图。
有三种广泛使用的编程范式:过程式编程、函数式编程和面向对象编程。Kotlin 都支持它们。在面向对象编程中,我们使用对象来解决复杂的问题。
面向对象编程 (OOP) 是一种使用对象及其交互来设计应用程序和计算机程序的编程范式。
Kotlin 类
对象是从类创建的。类是对象的蓝图;它以成员和成员函数的形式共享通用属性和行为。
在 Kotlin 中,使用 class 关键字声明一个类。
类声明由类名、类头(指定其类型参数、主构造函数等)和类体组成。类体在两个大括号内指定。类头和类体都是可选的。如果类没有类体,则可以省略大括号。
Kotlin 简单类示例
在下面的示例中,我们从一个类创建一个简单的对象。
package com.zetcode
class Simple {
private val name = "Simple"
fun info() = "This is $name class"
}
fun main() {
val s = Simple()
println(s)
println(s.info())
}
在示例中,我们声明一个 Simple 类,然后从中创建一个对象。
class Simple {
private val name = "Simple"
fun info() = "This is $name class"
}
在 Kotlin 中,使用 class 关键字创建类。在我们的类中,我们有一个属性(成员)和一个函数。
val s = Simple()
从 Simple 类创建一个新对象。在 Kotlin 中,我们不使用 new 关键字来创建实例。
println(s.info())
使用点运算符,我们调用对象的 info 函数。
com.zetcode.Simple@3cd1a2f1 This is Simple class
Kotlin 空类
在下面的示例中,我们创建了两个空类。
package com.zetcode
class Being {}
class Empty
fun main() {
val b = Being()
println(b)
val e = Empty()
println(e)
}
一个空类没有成员或成员函数。可以省略大括号。
Kotlin 主构造函数
一个 Kotlin 类可以有一个主构造函数和一个或多个次要构造函数。主构造函数是类头的一部分:它位于类名(和可选的类型参数)之后。
class User constructor(name: String, email: String) { }
这里我们使用 constructor 关键字。
class User (name: String, email: String) { }
如果主构造函数没有任何注解或可见性修饰符(例如 public),则可以省略 constructor 关键字。
主构造函数不能包含任何代码。初始化代码可以放在初始化块中,使用 init 关键字创建它们。
package com.zetcode
//class User constructor (_name: String, _email: String) {
class User(name: String, email: String) {
private val name = name
private val email = email
override fun toString(): String {
return "User $name has email $email"
}
}
fun main() {
val u = User("Peter Novak", "pnovak47@gmail.com")
println(u)
}
在示例中,我们有一个带主构造函数的 User 类。我们有两个成员和一个重写函数。
User Peter Novak has email pnovak47@gmail.com
Kotlin open 类
Kotlin 类默认是 final 的。其他类不能从 final 类继承。要使一个类可继承,我们用 open 关键字标记它。
package com.zetcode
open class Being(private val alive: Boolean = true) {
fun isAlive(): Boolean {
return alive
}
}
class Dog(val name: String): Being() {
fun bark(): String {
return "woof-woof"
}
}
fun main() {
val d = Dog("Rusty")
println(d.bark())
println(d.name)
println(d.isAlive())
}
我们有一个 open Being 类。Dog 类继承自 Being。
println(d.isAlive())
我们可以在 Dog 类上调用 isAlive 函数,因为它继承自其父类 Being 类。
woof-woof Rusty true
Kotlin 数据类
一些类被设计用来保存数据。使用数据类,我们可以大大减少样板代码。编译器会自动创建 equals、hashCode、toString 和 copy 函数。
在 Kotlin 中,使用 data 关键字创建数据类。
数据类必须遵循几个规则。主构造函数至少需要一个参数。所有主构造函数参数都必须标记为 val 或 var。数据类不能是 abstract、open、sealed 或 inner 的。
package com.zetcode
data class User(val name: String, val email: String)
fun main() {
val u = User("Peter Novak", "pnovak47@gmail.com")
println(u)
println(u.name)
println(u.email)
val (name, email) = u;
println("$name $email")
val u2 = User("Peter Novak", "pnovak47@gmail.com")
println(u == u2)
println(u === u2)
}
在示例中,我们有一个数据类:User。
data class User(val name: String, val email: String)
数据类以前缀 data 关键字开头。
val u = User("Peter Novak", "pnovak47@gmail.com")
println(u)
这里我们调用 toString 方法,它已经为我们创建好了。
val (name, email) = u;
println("$name $email")
我们可以使用解构声明从数据类中提取属性。
User(name=Peter Novak, email=pnovak47@gmail.com) Peter Novak pnovak47@gmail.com Peter Novak pnovak47@gmail.com true false
Kotlin 嵌套类
嵌套类在另一个类中声明。
package com.zetcode
class Outer {
val name = "Outer"
fun show() = "the name: $name"
class Nested {
val name = "Nested"
fun show() = "the name: $name"
}
}
fun main() {
println(Outer().show())
println(Outer.Nested().show())
}
为了访问嵌套类,我们指定其外部类的名称。因此,嵌套类的 show 函数被这样调用:Outer.Nested().show。嵌套类不能访问外部类的成员。
Kotlin 内部类
内部类是使用 inner 关键字创建的。与嵌套类不同,它们可以访问其外部类的成员。
package com.zetcode
class Outer {
val name1 = "Outer"
fun show() = "the name: $name1"
inner class Inner {
val name2 = "Inner"
fun show() = "data: $name2 and $name1"
}
}
fun main() {
println(Outer().show())
println(Outer().Inner().show())
}
在示例中,我们有一个内部类。它的 show 函数输出 Outer 类的 name1 成员。
Kotlin 抽象类
抽象类、成员或成员函数使用 abstract 关键字创建。如果一个类继承自一个抽象类,它必须实现其所有抽象成员和成员函数。实现的成员和成员函数必须以 override 关键字为前缀。我们不能从抽象类创建实例。抽象类是隐式 open 的,因为如果它们没有任何具体的子类,它们就毫无用处。
抽象类在概念上类似于接口。与接口不同,抽象类可以有状态。虽然一个类可以实现多个接口,但它只能继承一个抽象类。
抽象类用于构建类的层次结构;它们用作相关类的一些共享功能的组合。
package com.zetcode
abstract class Shape() {
abstract var w: Int
abstract var h: Int
abstract fun area(): Int
fun info(): String {
return "width: $w; height: $h"
}
}
class Rectangle(override var w: Int, override var h: Int): Shape() {
override fun area(): Int {
return w * h;
}
}
fun main() {
val r = Rectangle(5, 6)
println(r.area())
println(r.info());
}
在示例中,我们有一个抽象的 Shape 类。不可能创建一个形状,因为它太通用了。我们只能创建一个形状的后代;例如,一个矩形。
abstract var w: Int abstract var h: Int abstract fun area(): Int
这里我们有两个抽象变量和一个抽象函数。我们必须在子类中为它们提供实现。
Kotlin 密封类
密封类用于表示受限的类层次结构。一个值可以具有来自有限集合的类型之一,但不能具有任何其他类型。密封类比枚举类更强大。
密封类是抽象的,可以有抽象成员;这意味着它们不能直接实例化。密封类不能有公共构造函数(构造函数默认为私有)。密封类可以有子类,但它们必须在同一文件中或嵌套在密封类声明中。
package com.zetcode
sealed class Shape
class Circle(var radius: Float) : Shape()
class Square(var width: Int) : Shape()
class Rectangle(var width: Int, var height: Int) : Shape()
fun getArea(e: Shape) =
when (e) {
is Circle -> println("Circle area is ${Math.PI * e.radius * e.radius}")
is Square -> println("Square area is ${e.width * e.width}")
is Rectangle -> println("Rectangle area is ${e.width * e.height}")
}
fun main() {
val circle = Circle(7f)
val square = Square(5)
val rectangle = Rectangle(8, 6)
getArea(circle)
getArea(square)
getArea(rectangle)
}
在示例中,我们有一个密封的 Shape 类。它有三个子类:Circle、Square 和 Rectangle。
fun getArea(e: Shape) =
when (e) {
is Circle -> println("Circle area is ${Math.PI * e.radius * e.radius}")
is Square -> println("Square area is ${e.width * e.width}")
is Rectangle -> println("Rectangle area is ${e.width * e.height}")
}
getArea 函数计算形状的面积。请注意,不需要 else 语句,因为编译器知道选项列表是详尽的。
Circle area is 153.93804002589985 Square area is 25 Rectangle area is 48
package com.zetcode
sealed class Shape {
class Circle(var radius: Float) : Shape()
class Square(var width: Int) : Shape()
class Rectangle(var width: Int, var height: Int) : Shape()
}
fun getArea(e: Shape) =
when (e) {
is Shape.Circle -> println("Circle area is ${Math.PI * e.radius * e.radius}")
is Shape.Square -> println("Square area is ${e.width * e.width}")
is Shape.Rectangle -> println("Rectangle area is ${e.width * e.height}")
}
fun main() {
val circle = Shape.Circle(7f)
val square = Shape.Square(5)
val rectangle = Shape.Rectangle(8, 6)
getArea(circle)
getArea(square)
getArea(rectangle)
}
在此示例中,子类嵌套在 Shape 类中。
来源
在本文中,我们介绍了 Kotlin 中的类。
作者
列出 所有 Kotlin 教程。