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 教程。