重学仓颉-7类与接口完全指南:从基础到高级特性

引言

仓颉语言作为一门现代化的编程语言,提供了完整的面向对象编程支持

1. 类(Class)详解

1.1 类的基本概念

类(class)是面向对象编程中的核心概念,在仓颉中,类与结构体(struct)的主要区别在于:

  • 类是引用类型:赋值或传参时传递的是引用,多个变量指向同一个对象
  • 结构体是值类型:赋值或传参时进行值拷贝
  • 类支持继承:可以创建继承层次结构
  • 结构体不支持继承:只能实现接口

1.1.1 基本类定义

cangjie 复制代码
class Rectangle {
    let width: Int64
    let height: Int64

    public init(width: Int64, height: Int64) {
        this.width = width
        this.height = height
    }

    // public 成员函数,必须显式标注返回值类型
    public func area(): Int64 {
        width * height
    }
}

这个例子展示了类的基本结构:

  • 使用 class 关键字定义类
  • 包含成员变量 widthheight
  • 定义构造函数 init
  • 包含成员函数 area

1.1.2 抽象类

抽象类使用 abstract 关键字修饰,可以包含抽象函数(没有函数体的函数):

cangjie 复制代码
abstract class Shape {
    public func area(): Int64
    public func perimeter(): Int64

    public func description(): String {
        "A shape with area ${area()} and perimeter ${perimeter()}"
    }
}

重要注意点:

  • 抽象类中禁止定义 private 的抽象函数
  • 不能为抽象类创建实例
  • 抽象类的非抽象子类必须实现父类中的所有抽象函数

1.2 类成员详解

1.2.1 成员变量

类的成员变量分为实例成员变量和静态成员变量:

cangjie 复制代码
class Counter {
    // 实例成员变量
    var count: Int64 = 0
    let maxCount: Int64 = 100

    // 静态成员变量
    static let defaultMax: Int64 = 50
    static var totalInstances: Int64 = 0

    public init() {
        Counter.totalInstances += 1
    }

    public func increment(): Unit {
        if (count < maxCount) {
            count += 1
        }
    }

    public static func getDefaultMax(): Int64 {
        defaultMax
    }
}

关键特性:

  • 实例成员变量通过对象访问:counter.count
  • 静态成员变量通过类名访问:Counter.defaultMax
  • 静态成员变量在静态初始化器中初始化

1.2.2 静态初始化器

静态初始化器用于初始化静态成员变量:

cangjie 复制代码
class Configuration {
    static let appName: String
    static let version: String
    static let buildNumber: Int64

    static init() {
        appName = "MyApp"
        version = "1.0.0"
        buildNumber = 100
    }
}

限制条件:

  • 一个类中最多只能定义一个静态初始化器
  • 必须完成对所有未初始化的静态成员变量的初始化
  • 不能被访问修饰符修饰

1.2.3 构造函数

仓颉支持两种构造函数:普通构造函数和主构造函数。

普通构造函数:

cangjie 复制代码
class Person {
    let email: ?String

    // 主构造函数
    public Person(let name: String, let age: Int64) {
        this.email = None<String>
    }

    // 普通构造函数
    public init(name: String, age: Int64, email: String) {
        this.name = name
        this.age = age
        this.email = email
    }

    // 无参构造函数
    public init() {
        this.name = "Unknown"
        this.age = 0
        this.email = None<String>
    }
}

主构造函数:

  • 函数名与类名相同
  • 参数前加 letvar 可以同时定义成员变量
  • 最多只能有一个主构造函数
cangjie 复制代码
class Point {
    // 主构造函数,同时定义成员变量
    // public Point(let x: Int64, let y: Int64) {}

    // 或者混合使用
    public Point(name: String, let x: Int64, let y: Int64) {}
}

构造函数执行顺序:

  1. 初始化有缺省值的变量
  2. 调用父类构造函数(如果未显式调用)
  3. 执行构造函数体内的代码
cangjie 复制代码
open class Animal {
    init() {
        println("Animal constructor")
    }
}

class Dog <: Animal {
    var name = "Default"

    init() {
        // 这里可以省略super(),调用。如果我们没写,编译器会自动插入一个super的无参调用
        // super()
        name = "Buddy"
        println("Dog constructor")
    }
}

// 输出顺序:
// Animal constructor
// Dog constructor

1.2.4 终结器

终结器在对象被垃圾回收时触发,用于释放系统资源:

cangjie 复制代码
import std.core.LibC
class FileHandler {
    var filePath: String
    var fileHandle: CString

    init(path: String) {
        filePath = path

        fileHandle = unsafe { LibC.mallocCString("aaaaar") }
    }

    ~init() {
        unsafe { LibC.free(fileHandle) }
        println("File ${filePath} closed")
    }
}

终结器的重要限制:

  • 函数名固定为 ~init
  • 没有参数、返回类型、修饰符
  • 不能被显式调用
  • 执行时机不确定
  • 可能在任意线程上执行

1.2.5 成员函数

成员函数分为实例成员函数和静态成员函数:

cangjie 复制代码
class MathUtils {
    static let cnt: Int = 20
    // 实例成员函数
    public func add(a: Int64, b: Int64): Int64 {
        let cnt = MathUtils.cnt
        a + b
    }

    // 静态成员函数
    public static func factorial(n: Int64): Int64 {
        if (n <= 1) {
            1
        } else {
            n * factorial( n - 1)
        }
    }
}

函数访问规则:

  • 实例成员函数中能访问静态成员
  • 静态成员函数中不能访问实例成员
  • 实例成员函数中可以通过 this 访问实例成员

1.3 访问修饰符

仓颉提供四种访问修饰符:

cangjie 复制代码
package cangjie_blog.a

public open class Example {
    public var publicVar: Int64 = 1 // 模块内外均可见
    protected var protectedVar: Int64 = 2 // 当前模块及子类可见
    internal var internalVar: Int64 = 3 // 仅当前包及子包可见(默认)
    private var privateVar: Int64 = 4 // 仅在类定义内可见

    public func publicMethod() {}
    protected func protectedMethod() {}
    internal func internalMethod() {}
    private func privateMethod() {}
}

访问级别总结:

  • private:类内部可见
  • internal:包内可见(默认)
  • protected:模块内及子类可见
  • public:模块内外均可见

1.4 This 类型

This 类型是类的特殊类型占位符,代表当前类的类型:

cangjie 复制代码
open class Builder {
    func build(): This {
        this
    }

    func chain(): This {
        // 返回当前对象,支持链式调用
        this
    }
}

class StringBuilder <: Builder {
    var content: String = ""

    func append(str: String): This {
        content += str
        this
    }
}

main() {
    let builder = StringBuilder()
    let result = builder.append("Hello").append(" World").build()
    println("result is StringBuilder ${result is StringBuilder}")
    // result 的类型是 StringBuilder,不是 Builder
}

This 类型的特性:

  • 只能作为实例成员函数的返回类型
  • 支持多态返回类型
  • 子类调用时返回类型会被识别为子类类型

1.5 对象创建与使用

1.5.1 创建对象

cangjie 复制代码
class Car {
    var brand: String
    var model: String
    var year: Int64
    // 构造函数也是函数,支持命名参数
    public init(brand!: String, model!: String, year!: Int64) {
        this.brand = brand
        this.model = model
        this.year = year
    }

    public func getInfo(): String {
        "${year} ${brand} ${model}"
    }
}

main() {
    // 创建对象
    let car = Car(brand: "Toyota", model: "Camry", year: 2023)

    // 访问成员
    println(car.brand)        // Toyota
    println(car.getInfo())    // 2023 Toyota Camry

    // 修改成员(需要 var 修饰)
    car.year = 2024
    println(car.getInfo())    // 2024 Toyota Camry
}

1.5.2 引用类型特性

类作为引用类型,赋值时传递的是引用:

cangjie 复制代码
class Counter {
    var value: Int64 = 0

    public func increment() {
        value += 1
    }

    public func getValue(): Int64 {
        value
    }
}

main() {
    let counter1 = Counter()
    let counter2 = counter1 // 传递引用,不是拷贝

    counter1.increment()
    println(counter1.getValue()) // 1
    println(counter2.getValue()) // 1,因为指向同一个对象

    counter2.increment()
    println(counter1.getValue()) // 2
    println(counter2.getValue()) // 2
}

1.6 类的继承

1.6.1 基本继承

cangjie 复制代码
open class Animal {
    var name: String
    var age: Int64

    public init(name: String, age: Int64) {
        this.name = name
        this.age = age
    }

    // 允许被重写的方法需要使用open修饰
    open public func makeSound(): String {
        "Some sound"
    }

    public func getInfo(): String {
        "Name: ${name}, Age: ${age}"
    }
}

class Dog <: Animal {
    var breed: String

    public init(name: String, age: Int64, breed: String) {
        super(name, age) // 调用父类构造函数
        this.breed = breed
    }

    public override func makeSound(): String {
        "Woof!"
    }

    public func getBreed(): String {
        breed
    }
}

class Cat <: Animal {
    var color: String

    public init(name: String, age: Int64, color: String) {
        super(name, age)
        this.color = color
    }

    public override func makeSound(): String {
        "Meow!"
    }
}

继承规则:

  • 使用 <: 表示继承关系
  • 只有 open 修饰的类才能被继承
  • 抽象类总是可被继承
  • 类只支持单继承

1.6.2 构造函数调用

子类构造函数必须调用父类构造函数:

cangjie 复制代码
open class Base {
    var value: Int64

    public init(value: Int64) {
        this.value = value
    }

    public init() {
        this.value = 0
    }
}

class Derived <: Base {
    var name: String

    public init(value: Int64, name: String) {
        super(value)  // 显式调用父类构造函数
        this.name = name
    }

    public init(name: String) {
        super()       // 调用父类无参构造函数
        this.name = name
    }

    public init() {
        super()       // 调用父类无参构造函数
        this.name = "Default"
    }
}

构造函数调用规则:

  • 必须使用 super(args) 调用父类构造函数
  • 或使用 this(args) 调用本类其他构造函数
  • 调用必须在构造函数体的第一个表达式处
  • 如果未显式调用,编译器会自动插入 super()

1.6.3 函数覆盖

子类可以覆盖父类的 open 函数:

cangjie 复制代码
open class Shape {
    public open func area(): Int64 {
        0
    }

    public open func perimeter(): Int64 {
        0
    }
}

class Rectangle <: Shape {
    var width: Int64
    var height: Int64

    public init(width: Int64, height: Int64) {
        this.width = width
        this.height = height
    }

    public override func area(): Int64 {
        width * height
    }

    public override func perimeter(): Int64 {
        2 * (width + height)
    }
}

class Circle <: Shape {
    var radius: Int64

    public init(radius: Int64) {
        this.radius = radius
    }

    public override func area(): Int64 {
        // 简化的圆形面积计算
        3 * radius * radius
    }

    public override func perimeter(): Int64 {
        2 * 3 * radius
    }
}

覆盖规则:

  • 父类函数必须使用 open 修饰
  • 子类函数使用 override 修饰(可选)
  • 函数签名必须完全匹配
  • 支持动态派发

1.6.4 静态函数重定义

子类可以重定义父类的静态函数:

cangjie 复制代码
open class Base {
    public static func getType(): String {
        "Base"
    }

    public static func getVersion(): String {
        "1.0"
    }
}

class Derived <: Base {
    public static redef func getType(): String {
        "Derived"
    }

    // 不重定义 getVersion,继承父类实现
}

main() {
    println(Base.getType()) // Base
    println(Base.getVersion()) // 1.0
    println(Derived.getType()) // Derived
    println(Derived.getVersion()) // 1.0
}

重定义规则:

  • 使用 redef 修饰符(可选)
  • 静态函数不支持动态派发
  • 根据类类型决定调用版本

1.6.5 继承性修饰符

cangjie 复制代码
// 可继承的类
public open class OpenClass {}

// 不可继承的类(默认)
class FinalClass {}

// 抽象类(总是可被继承)
// 默认修饰符internal
abstract class AbstractClass {
    public func abstractMethod(): Unit
}

// 密封抽象类(只能在本包被继承)
abstract sealed class SealedAbstractClass {
    public func abstractMethod(): Unit
}

// 继承示例
class SubClass <: OpenClass {} // OK

class SubAbstract <: AbstractClass { // OK
    public func abstractMethod(): Unit {
    }
}

class SubSealed <: SealedAbstractClass { // OK(同包内)
    public func abstractMethod(): Unit {}
}

// 这些继承会报错
// class SubFinal <: FinalClass {}      // Error
// class SubOpen <: SubClass {}        // Error(SubClass 不是 open 的)

2. 接口(Interface)详解

2.1 接口基本概念

接口定义抽象类型,不包含数据,但可以定义类型的行为:

cangjie 复制代码
interface Drawable {
    func draw(): Unit
    func getArea(): Int64
}

interface Movable {
    func move(x: Int64, y: Int64): Unit
    func getPosition(): (Int64, Int64)
}

接口特性:

  • 成员都是抽象的(除非有默认实现)
  • 实现类型必须提供所有成员的实现
  • 支持多重实现
  • 可以继承其他接口

2.2 接口成员

2.2.1 实例成员

cangjie 复制代码
interface Vehicle {
    func start(): Unit
    func stop(): Unit
    func getSpeed(): Int64
    func setSpeed(speed: Int64): Unit
}

class Car <: Vehicle {
    private var speed: Int64 = 0
    private var isRunning: Bool = false

    public func start(): Unit {
        isRunning = true
        println("Car started")
    }

    public func stop(): Unit {
        isRunning = false
        speed = 0
        println("Car stopped")
    }

    public func getSpeed(): Int64 {
        speed
    }

    public func setSpeed(speed: Int64): Unit {
        if (isRunning) {
            this.speed = speed
        }
    }
}

2.2.2 静态成员

cangjie 复制代码
interface Factory {
    static func create(): Factory
    static func getType(): String
}

class CarFactory <: Factory {
    public static func create(): CarFactory {
        CarFactory()
    }

    public static func getType(): String {
        "CarFactory"
    }
}

class BikeFactory <: Factory {
    public static func create(): BikeFactory {
        BikeFactory()
    }

    public static func getType(): String {
        "BikeFactory"
    }
}

2.2.3 默认实现

接口可以提供默认实现:

cangjie 复制代码
interface Logger {
    func log(message: String): Unit {
        println("[${getTimestamp()}] ${message}")
    }

    func getTimestamp(): String

    func logError(error: String): Unit {
        log("ERROR: ${error}")
    }
}

class ConsoleLogger <: Logger {
    public func getTimestamp(): String {
        // 简化的时间戳
        "2024-01-01 12:00:00"
    }

    // 继承 log 和 logError 的默认实现
}

class FileLogger <: Logger {
    public func getTimestamp(): String {
        "2024-01-01 12:00:00"
    }

    // 覆盖默认实现
    public override func log(message: String): Unit {
        println("FILE: ${message}")
    }
}

2.3 接口实现

2.3.1 单接口实现

cangjie 复制代码
interface Printable {
    func print(): Unit
    func getContent(): String
}

class Document <: Printable {
    private var content: String

    public init(content: String) {
        this.content = content
    }

    public func print(): Unit {
        println("Printing: ${content}")
    }

    public func getContent(): String {
        content
    }
}

2.3.2 多接口实现

使用 & 分隔多个接口:

cangjie 复制代码
interface Readable {
    func read(): String
}

interface Writable {
    func write(content: String): Unit
}

interface ReadWriteable <: Readable & Writable {
    func clear(): Unit
}

class TextFile <: ReadWriteable {
    private var content: String = ""

    public func read(): String {
        content
    }

    public func write(content: String): Unit {
        this.content = content
    }

    public func clear(): Unit {
        content = ""
    }
}

2.3.3 接口继承

cangjie 复制代码
interface Animal {
    func makeSound(): String
}

interface Pet <: Animal {
    func getName(): String
    func play(): Unit
}

interface Dog <: Pet {
    func wagTail(): Unit
}

class GoldenRetriever <: Dog {
    private var name: String

    public init(name: String) {
        this.name = name
    }

    public func makeSound(): String {
        "Woof!"
    }

    public func getName(): String {
        name
    }

    public func play(): Unit {
        println("${name} is playing fetch")
    }

    public func wagTail(): Unit {
        println("${name} is wagging tail")
    }
}

2.4 接口冲突解决

当多个接口有相同成员的默认实现时,需要显式实现:

cangjie 复制代码
interface Logger {
    func log(message: String): Unit {
        println("Logger: ${message}")
    }
}

interface Printer {
    func log(message: String): Unit {
        println("Printer: ${message}")
    }
}

class Device <: Logger & Printer {
    // 必须显式实现,避免冲突
    public func log(message: String): Unit {
        println("Device: ${message}")
    }
}

2.5 Any 类型

Any 是所有类型的基接口:

cangjie 复制代码
// 所有类型都默认实现 Any
main() {
    var any: Any = 42
    any = "Hello"
    any = true
    any = 3.14
}

3. 属性(Properties)详解

3.1 属性基本概念

属性提供 getter 和可选的 setter 来间接访问值:

cangjie 复制代码
class BankAccount {
    private var balance: Int64 = 0

    // 只读属性
    public prop currentBalance: Int64 {
        get() {
            balance
        }
    }

    // 读写属性
    public mut prop accountBalance: Int64 {
        get() {
            balance
        }
        // set这里不需要写类型,也不让写类型。由编译器自动推断
        set(value) {
            if (value >= 0) {
                balance = value
            }
        }
    }

    // 计算属性
    public prop isOverdrawn: Bool {
        get() {
            balance < 0
        }
    }
}

3.2 属性类型

3.2.1 只读属性

cangjie 复制代码
class Circle {
    private let radius: Int64

    public init(radius: Int64) {
        this.radius = radius
    }

    public prop diameter: Int64 {
        get() {
            radius * 2
        }
    }

    public prop circumference: Int64 {
        get() {
            2 * 3 * radius  // 简化的圆周率
        }
    }
}

3.2.2 读写属性

cangjie 复制代码
class Temperature {
    private var celsius: Float64 = 0.0

    public mut prop temperature: Float64 {
        get() {
            celsius
        }
        set(value) {
            celsius = value
        }
    }

    public mut prop fahrenheit: Float64 {
        get() {
            celsius * 9.0 / 5.0 + 32.0
        }
        set(value) {
            celsius = (value - 32.0) * 5.0 / 9.0
        }
    }
}

3.3 静态属性

cangjie 复制代码
import std.collection.HashMap

class Configuration {
    private static var instance: ?Configuration = None<Configuration>
    private var settings: HashMap<String, String> = HashMap<String, String>()

    public static prop shared: Configuration {
        get() {
            // 使用标准库ifNone函数
            ifNone(instance) {
                instance = Configuration()
            }
            instance.getOrThrow()
        }
    }

    public mut prop serverUrl: String {
        get() {
            settings.get("serverUrl") ?? "localhost:8080"
        }
        set(value) {
            settings.add("serverUrl", value)
        }
    }
}

3.4 属性继承与覆盖

cangjie 复制代码
open class Base {
    public open prop value: Int64 {
        get() {
            0
        }
    }

    public open mut prop mutableValue: Int64 {
        get() {
            0
        }
        set(v) {
            // 基类实现
        }
    }
}

class Derived <: Base {
    private var actualValue: Int64 = 42

    public override prop value: Int64 {
        get() {
            actualValue
        }
    }

    public override mut prop mutableValue: Int64 {
        get() {
            actualValue
        }
        set(v) {
            actualValue = v
        }
    }
}

4. 子类型关系

4.1 继承带来的子类型关系

cangjie 复制代码
open class Animal {}
class Dog <: Animal {}
class Cat <: Animal {}

// Dog 和 Cat 都是 Animal 的子类型
func feed(animal: Animal): Unit {
    println("Feeding animal")
}

main() {
    let dog = Dog()
    let cat = Cat()

    feed(dog)  // OK: Dog <: Animal
    feed(cat)  // OK: Cat <: Animal
}

4.2 接口实现带来的子类型关系

cangjie 复制代码
interface Movable {
    func move(): Unit
}

interface Eatable {
    func eat(): Unit
}

class Bird <: Movable & Eatable {
    public func move(): Unit {
        println("Bird is flying")
    }

    public func eat(): Unit {
        println("Bird is eating")
    }
}

// Bird 是 Movable 和 Eatable 的子类型
func processMovable(movable: Movable): Unit {
    movable.move()
}

func processEatable(eatable: Eatable): Unit {
    eatable.eat()
}

main() {
    let bird = Bird()
    processMovable(bird)  // OK: Bird <: Movable
    processEatable(bird)  // OK: Bird <: Eatable
}

4.3 元组类型的子类型关系

cangjie 复制代码
open class Base {}
class Derived <: Base {}

// (Derived, Derived) <: (Base, Base)
let tuple1: (Base, Base) = (Derived(), Derived())

4.4 函数类型的子类型关系

cangjie 复制代码
open class Base {}
class Derived <: Base {}

// 如果 Derived <: Base,那么 (Base) -> Derived <: (Derived) -> Base
func processBase(base: Base): Derived {
    Derived()
}

func processDerived(derived: Derived): Base {
    derived
}

// processBase 的类型是 processDerived 的子类型

5. 类型转换

5.1 数值类型转换

cangjie 复制代码
main() {
    let int8Value: Int8 = 100
    let int16Value: Int16 = 1000
    let float32Value: Float32 = 3.14

    // 显式类型转换
    let convertedInt16 = Int16(int8Value)
    let convertedInt8 = Int8(int16Value)
    let convertedFloat64 = Float64(float32Value)

    println("Int8 to Int16: ${convertedInt16}")
    println("Int16 to Int8: ${convertedInt8}")
    println("Float32 to Float64: ${convertedFloat64}")
}

5.2 字符类型转换

cangjie 复制代码
main() {
    let char: Rune = 'A'
    let unicodeValue = UInt32(char)

    let number: UInt32 = 66
    let charFromNumber = Rune(number)

    println("Character '${char}' has Unicode value: ${unicodeValue}")
    println("Unicode value ${number} represents character: '${charFromNumber}'")
}

5.3 类型检查与转换

5.3.1 is 操作符

cangjie 复制代码
open class Shape {}

class Circle <: Shape {}

class Rectangle <: Shape {}

main() {
    let shapes: Array<Shape> = [Circle(), Rectangle(), Circle()]

    for (shape in shapes) {
        // 这里可以修改为match
        if (shape is Circle) {
            println("Found a circle")
        } else if (shape is Rectangle) {
            println("Found a rectangle")
        } else {
            println("Found a shape")
        }
    }
}

5.3.2 as 操作符

cangjie 复制代码
open class Animal {}

class Dog <: Animal {}

class Cat <: Animal {}

func processDog(dog: Dog): Unit {
    println("Processing dog")
}

main() {
    let animals: Array<Animal> = [Dog(), Cat(), Dog()]

    for (animal in animals) {
        // 尝试转换为 Dog 类型
        let dogOption = animal as Dog
        match (dogOption) {
            case Some(dog) => processDog(dog)
            case None => println("Not a dog")
        }
    }
}

6. 实际应用场景

6.1 设计模式实现

6.1.1 策略模式

cangjie 复制代码
interface PaymentStrategy {
    func pay(amount: Int64): Unit
}

class CreditCardPayment <: PaymentStrategy {
    private var cardNumber: String

    public init(cardNumber: String) {
        this.cardNumber = cardNumber
    }

    public func pay(amount: Int64): Unit {
        println("Paid ${amount} using credit card ending in ${cardNumber}")
    }
}

class PayPalPayment <: PaymentStrategy {
    private var email: String

    public init(email: String) {
        this.email = email
    }

    public func pay(amount: Int64): Unit {
        println("Paid ${amount} using PayPal account ${email}")
    }
}

class ShoppingCart {
    private let items: ArrayList<String> = ArrayList()
    private var paymentStrategy: ?PaymentStrategy = None<PaymentStrategy>

    public func addItem(item: String): Unit {
        items.add(item)
    }

    public func setPaymentStrategy(strategy: PaymentStrategy): Unit {
        paymentStrategy = strategy
    }

    public func checkout(): Unit {
        let total = items.size * 10 // 假设每件商品10元
        if (let Some(strategy) <- paymentStrategy) {
            strategy.pay(total)
        } else {
            println("No payment strategy set")
        }
    }
}

main() {
    let s = ShoppingCart()
    s.addItem("one piece")

    s.setPaymentStrategy(CreditCardPayment("12345"))
    s.checkout()
    s.setPaymentStrategy(PayPalPayment("67890"))
    s.checkout()
}

6.1.2 工厂模式

cangjie 复制代码
interface Vehicle {
    func start(): Unit
    func stop(): Unit
}

class Car <: Vehicle {
    public func start(): Unit {
        println("Car started")
    }

    public func stop(): Unit {
        println("Car stopped")
    }
}

class Motorcycle <: Vehicle {
    public func start(): Unit {
        println("Motorcycle started")
    }

    public func stop(): Unit {
        println("Motorcycle stopped")
    }
}

interface VehicleFactory {
    static func createVehicle(): Vehicle
}

class CarFactory <: VehicleFactory {
    public static func createVehicle(): Vehicle {
        Car()
    }
}

class MotorcycleFactory <: VehicleFactory {
    public static func createVehicle(): Vehicle {
        Motorcycle()
    }
}

// 由于仓颉中没给出元类型的语法。所以以下方式无法实现。
// 正确的语法应该类似 VehicleFactory.This这样的语法
func createAndUseVehicle(factory: VehicleFactory): Unit {
    // object cannot access static member 'createVehicle'
    let vehicle = factory.createVehicle()
    vehicle.start()
    vehicle.stop()
}

6.2 数据模型设计

cangjie 复制代码
import std.time.DateTime

interface Identifiable {
    func getId(): String
}

interface Timestamped {
    func getCreatedAt(): Int64
    func getUpdatedAt(): Int64
}

open class BaseEntity <: Identifiable & Timestamped {
    private let id: String
    private let createdAt: Int64
    private var updatedAt: Int64

    public init(id: String) {
        this.id = id
        this.createdAt = DateTime.now().nanosecond
        this.updatedAt = this.createdAt
    }

    public func getId(): String {
        id
    }

    public func getCreatedAt(): Int64 {
        createdAt
    }

    public func getUpdatedAt(): Int64 {
        updatedAt
    }

    protected func updateTimestamp(): Unit {
        updatedAt = getCurrentTimestamp()
    }

    private func getCurrentTimestamp(): Int64 {
        // 简化的时间戳获取
        1640995200 // 2022-01-01 00:00:00
    }
}

class User <: BaseEntity {
    private var username: String
    private var email: String

    public init(id: String, username: String, email: String) {
        super(id)
        this.username = username
        this.email = email
    }

    public func getUsername(): String {
        username
    }

    public func getEmail(): String {
        email
    }

    public func updateEmail(email: String): Unit {
        this.email = email
        updateTimestamp()
    }
}

class Post <: BaseEntity {
    private var title: String
    private var content: String
    private var authorId: String

    public init(id: String, title: String, content: String, authorId: String) {
        super(id)
        this.title = title
        this.content = content
        this.authorId = authorId
    }

    public func getTitle(): String {
        title
    }

    public func getContent(): String {
        content
    }

    public func getAuthorId(): String {
        authorId
    }

    public func updateContent(content: String): Unit {
        this.content = content
        updateTimestamp()
    }
}

7. 最佳实践与注意事项

7.1 类设计原则

  1. 单一职责原则:每个类应该只有一个职责
  2. 开闭原则:对扩展开放,对修改关闭
  3. 里氏替换原则:子类应该能够替换父类
  4. 接口隔离原则:接口应该小而专注
  5. 依赖倒置原则:依赖抽象而不是具体实现

7.2 性能考虑

cangjie 复制代码
class OptimizedProcessor {
    private static let sharedBuffer: ArrayList<Int64> = ArrayList()

    public static func processBatch(items: Array<Int64>): Array<Int64> {
        // 重用缓冲区而不是每次都创建新的
        sharedBuffer.clear()
        for (item in items) {
            sharedBuffer.add(item * 2)
        }

        sharedBuffer.clone().toArray()
    }
}

// 使用对象池模式
class ObjectPool<T> where T <: Equatable<T> {
    private var available: ArrayList<T> = ArrayList()
    private var inUse: ArrayList<T> = ArrayList()

    public func acquire(): ?T {
        if (available.isEmpty()) {
            None
        } else {
            let obj = available.remove(at: 0)
            inUse.add(obj)
            obj
        }
    }

    public func release(obj: T): Unit {
        inUse.removeIf {t => t == obj}
        available.add(obj)
    }
}

7.3 错误处理

cangjie 复制代码
interface Result<T, E> {
    func isSuccess(): Bool
    func isError(): Bool
    func getValue(): ?T
    func getError(): ?E
}

class Success<T, E> <: Result<T, E> {
    private var value: T

    public init(value: T) {
        this.value = value
    }

    public func isSuccess(): Bool {
        true
    }

    public func isError(): Bool {
        false
    }

    public func getValue(): ?T {
        value
    }

    public func getError(): ?E {
        None<E>
    }
}

class Error<T, E> <: Result<T, E> {
    private var error: E

    public init(error: E) {
        this.error = error
    }

    public func isSuccess(): Bool {
        false
    }

    public func isError(): Bool {
        true
    }

    public func getValue(): ?T {
        None<T>
    }

    public func getError(): ?E {
        error
    }
}

参考资料

相关推荐
被开发耽误的大厨4 小时前
鸿蒙ArkUI 基础篇-06-组件基础语法-Column/Row/Text
华为·harmonyos
HarderCoder9 小时前
重学仓颉-6枚举与模式匹配完全指南
harmonyos
li理9 小时前
鸿蒙应用开发完全指南:深度解析UIAbility、页面与导航的生命周期
前端·harmonyos
HarderCoder11 小时前
重学仓颉-5结构体(Struct)完全指南:从基础到高级用法
harmonyos
HarmonyOS小助手12 小时前
【推荐+1】HarmonyOS官方模板优秀案例 (第4期:餐饮行业 · 美食菜谱)
harmonyos·鸿蒙·鸿蒙生态
HarderCoder13 小时前
重学仓颉-4函数系统完全指南
harmonyos
HarderCoder18 小时前
重学仓颉-3基本数据类型详解:从理论到实践的全面指南
harmonyos
鸿蒙小灰18 小时前
鸿蒙OpenCV移植技术要点
opencv·harmonyos
鸿蒙先行者18 小时前
鸿蒙分布式能力调用失败解决方案及案例
分布式·harmonyos