class 类型是面向对象编程中的经典概念,仓颉中同样支持使用 class 来实现面向对象编程。class 与 struct 的主要区别在于:class 是引用类型,struct 是值类型,它们在赋值或传参时行为是不同的;class 之间可以继承,但 struct 之间不能继承。
本节依次介绍如何定义 class 类型,如何创建对象,以及 class 的继承。
class 定义
class 类型的定义以关键字 class 开头,后跟 class 的名字,接着是定义在一对花括号中的 class 定义体。class 定义体中可以定义一系列的成员变量、成员属性(参见属性)、静态初始化器、构造函数、成员函数和操作符函数(详见操作符重载章节))。
class Rectangle {
let width: Int64
let height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public func area() {
width * height
}
}
上例中定义了名为 Rectangle 的 class 类型,它有两个 Int64 类型的成员变量 width 和 height,一个有两个 Int64 类型参数的构造函数,以及一个成员函数 area(返回 width 和 height 的乘积)。
注意
class 只能定义在源文件顶层。
class 成员变量
class 成员变量分为实例成员变量和静态成员变量,静态成员变量使用 static 修饰符修饰,必须有初值,只能通过类型名访问,参考如下示例:
class Rectangle {
let width = 10
static let height = 20
}
let l = Rectangle.height // l = 20
实例成员变量定义时可以不设置初值(但必须标注类型),也可以设置初值,只能通过对象(即类的实例)访问,参考如下示例:
class Rectangle {
let width = 10
let height: Int64
init(h: Int64){
height = h
}
}
let rec = Rectangle(20)
let l = rec.height // l = 20
class 静态初始化器
class 支持定义静态初始化器,并在静态初始化器中通过赋值表达式来对静态成员变量进行初始化。
静态初始化器以关键字组合 static init 开头,后跟无参参数列表和函数体,且不能被访问修饰符修饰。函数体中必须完成对所有未初始化的静态成员变量的初始化,否则编译报错。
class Rectangle {
static let degree: Int64
static init() {
degree = 180
}
}
一个 class 中最多允许定义一个静态初始化器,否则报重定义错误。
class Rectangle {
static let degree: Int64
static init() {
degree = 180
}
static init() { // Error, redefinition with the previous static init function
degree = 180
}
}
class 构造函数
和 struct 一样,class 中也支持定义普通构造函数和主构造函数。
普通构造函数以关键字 init 开头,后跟参数列表和函数体,函数体中必须完成所有未初始化实例成员变量的初始化,否则编译报错。
class Rectangle {
let width: Int64
let height: Int64
public init(width: Int64, height: Int64) { // Error, 'height' is not initialized in the constructor
this.width = width
}
}
一个类中可以定义多个普通构造函数,但它们必须构成重载(参见函数重载),否则报重定义错误。
class Rectangle {
let width: Int64
let height: Int64
public init(width: Int64) {
this.width = width
this.height = width
}
public init(width: Int64, height: Int64) { // Ok: overloading with the first init function
this.width = width
this.height = height
}
public init(height: Int64) { // Error, redefinition with the first init function
this.width = height
this.height = height
}
}
除了可以定义若干普通的以 init 为名字的构造函数外,class 内还可以定义(最多)一个主构造函数。主构造函数的名字和 class 类型名相同,它的参数列表中可以有两种形式的形参:普通形参和成