第六章 类继承和接口继承 示例代码

浙江传媒学院 · 仓颉面向对象程序设计 · 基于 CangStream 框架构建

示例程序
25 个
程序实例
6 个
代码合计
31 个

一、类继承(6.1)

例6-1 Person 类与 Student 类

6.1.2:open class Person 含 name/age/sex 三字段,Student 用 <: 继承并新增 department,重写 print() 方法。

package demo
// 可继承的基类:Person
open class Person {
    protected var name: String
    protected var age: Int64
    protected var sex: String
    public init(name: String, age: Int64, sex: String) {
        this.name = name
        this.age = age
        this.sex = sex
    }
   //  可重写的基类方法:
   open public func print(): Unit {
        println("姓名:${name},年龄:${age},性别:${sex}")
    }
}
// Student 类继承 Person,使用 <: 语法
class Student <: Person {
    protected var department: String
    public init(name: String, age: Int64, sex: String, department: String) {
        super(name, age, sex)  // 调用父类构造函数
        this.department = department // 派生类中增加一个新的成员
    }
    // 重写基类方法
    public override func print(): Unit {
        println("姓名:${name},年龄:${age},性别:${sex},专业:${department}")
    }
}
main(): Int64 {
    let p = Person("张三", 45, "男")
    p.print()
    let s = Student("李四", 20, "女", "计算机科学与技术")
    s.print()
    return 0
}

二、抽象类与抽象方法(6.2)

例6-2 抽象类及抽象方法的应用

abstract class Person 声明抽象方法 print(),子类 Student 必须实现该方法。

package demo
// 抽象基类:Person,允许被继承
abstract class Person {
    protected var name: String
    protected var age: Int64
    protected var sex: String

    public init(name: String, age: Int64, sex: String) {
        this.name = name
        this.age = age
        this.sex = sex
    }
    // 抽象方法:子类必须实现
    open public func print(): Unit
}
// Student 类继承 Person,并实现 print 方法
class Student <: Person {
    protected var department: String

    public init(name: String, age: Int64, sex: String, department: String) {
        super(name, age, sex)
        this.department = department
    }
    // 实现/重写父类抽象方法
    public override func print(): Unit {
        println("姓名:${name},年龄:${age},性别:${sex},专业:${department}")
    }
}
main(): Int64 {
    let s = Student("李四", 20, "女", "计算机科学与技术")
    s.print()
    return 0
}

例6-3 多级继承示例

abstract Person → open Student → GroupMember 三级继承链,GroupMember 新增 groupId 字段。

package demo
// 抽象可继承的基类:Person
abstract class Person {
    protected var name: String
    protected var age: Int64
    protected var sex: String
    public init(name: String, age: Int64, sex: String) {
        this.name = name
        this.age = age
        this.sex = sex
    }
    // 抽象方法:必须由子类实现
    open public func print(): Unit
}
// Student 类继承 Person
open class Student <: Person {
    protected var department: String
    public init(name: String, age: Int64, sex: String, department: String) {
        super(name, age, sex)
        this.department = department
    }
    // 重写 print 方法
    open public override func print(): Unit {
        println("姓名:${name},年龄:${age},性别:${sex},专业:${department}")
    }
}
// GroupMember 类从 Student 派生,新增 groupId 字段
class GroupMember <: Student {
    protected var groupId: Int64
    public init(name: String, age: Int64, sex: String, department: String, groupId: Int64) {
        super(name, age, sex, department)
        this.groupId = groupId
    }
    // 重写 print 方法,输出全部信息
    public override func print(): Unit {
        println("姓名:${name},年龄:${age},性别:${sex},专业:${department},组号:${groupId}")
    }
}
main(): Int64 {
    let gm = GroupMember("王五", 21, "男", "人工智能", 3)
    gm.print()
    return 0
}

三、类继承中的对象赋值(6.3)

例6-4 类继承中的对象赋值

派生类对象可赋值给基类变量,调用 print() 时根据实际对象类型动态绑定方法。

package demo
open class Person {
    protected var name: String
    protected var age: Int64
    protected var sex: String
    public init(name: String, age: Int64, sex: String) {
        this.name = name
        this.age = age
        this.sex = sex
    }
   open public func print(): Unit {
        println("姓名:${name},年龄:${age},性别:${sex}")
    }
}
open class Student <: Person {
    protected var department: String
    public init(name: String, age: Int64, sex: String, department: String) {
        super(name, age, sex)
        this.department = department
    }
    open public override func print(): Unit {
        println("姓名:${name},年龄:${age},性别:${sex},专业:${department}")
    }
}
main(): Int64 {
    var myperson=Person("王五", 21, "男")
     myperson.print()
    var mygm=Student("王五", 21, "男", "人工智能")
    myperson=mygm
    myperson.print()
    return 0
}

四、父类构造函数与 super 关键字(6.4)

例6-5 子类及 super 关键字

Person 含 name/age 两字段和 printInfo() 方法,Student 通过 super(name, age) 调用父类构造函数。

package demo
// 基类 Person
open class Person {
    protected var name: String
    protected var age: Int64
    public init(name: String, age: Int64) {
        this.name = name
        this.age = age
    }
    // 可重写的基类方法:printInfo
    open public func printInfo(): Unit {
        println("姓名:${name},年龄:${age}")
    }
}
// 子类 Student 继承 Person
class Student <: Person {
    protected var department: String
    // 子类构造函数,通过 super() 调用父类构造函数
    public init(name: String, age: Int64, department: String) {
        super(name, age)  // 调用父类的构造函数来初始化父类成员
        this.department = department
    }
    // 重写 printInfo 方法
    public override func printInfo(): Unit {
        println("姓名:${name},年龄:${age},专业:${department}")
    }
}
main(): Int64 {
    // 创建 Student 对象,构造函数调用父类的构造函数
    let student = Student("李四", 20, "计算机科学")
    student.printInfo()
    return 0
}

例6-6 自动调用父类无参构造函数

Animal 有无参 init(),Dog 的构造函数未显式调用 super,编译器自动调用父类无参构造函数。

package demo
open class Animal {
    public var name: String
    init() {
        name = "Unknown"
    }
}
class Dog<:Animal {
    public var breed: String
    init(breed: String) {
        this.breed = breed
        // 编译器自动调用父类的无参构造函数
    }
}
main(){
    let dog = Dog("Bulldog")
    println(dog.name)  // 输出 "Unknown"
    }

例6-7 显式调用父类的某个构造函数

Animal 有无参和带参两个构造函数,Dog 用 super(name, age) 显式选择带参版本。

package demo
open class Animal {              // 定义父类 Animal
    var name: String
    var age: Int64  
    init() {  // 不带参数的构造函数
       name = "Unknown"
       age = 0
    }    
    init(name: String, age: Int64) { // 带参数的构造函数
       this.name = name
       this.age = age
    }     
      open public func printInfo():Unit { // 打印信息的方法
       println("Name: ${this.name}, Age: ${this.age}")
    }
}
class Dog<:Animal { // 定义子类 Dog,继承自 Animal
    var breed: String
    // 子类的构造函数
    init(name: String, age: Int64,breed: String) {
       super(name,age) // 显式调用父类带参数的构造函数
       this.breed = breed 
    }    
   public override func printInfo() { // 重写父类的方法
      println("Breed: ${this.breed}, Name: ${this.name}, Age: ${this.age}")
    }
}
main() {
    // 创建一个 Dog 对象
    let dog = Dog("Haqi",3,"Golden Retriever")
    // 调用重写后的方法,打印信息
    dog.printInfo() // 输出: Breed: Golden Retriever, Name: Dog, Age: 3
}

五、覆盖和重定义(6.5)

例6-8 派生类中同名函数的覆盖示例

Teacher/Student 各有 print() 方法,运行时根据对象实际类型调用对应的 override 版本。

package demo
// 定义父类 Teacher
open class Teacher {
    public open func print(): Unit {
       println("I am Teacher")
    }
}
// 定义子类 Student,继承自 Teacher
class Student <: Teacher {
    public override func print(): Unit {
        println("I am Student")
    }
}
main() {
    // 创建 Teacher 和 Student 对象
    let teacher: Teacher = Teacher()
    let student: Teacher = Student()
    // 调用 print() 方法
    teacher.print() // 输出: I am Teacher
    student.print() // 输出: I am Student
}

例6-9 静态函数的重定义示例

静态函数不参与 override 机制,Teacher.print() 和 Student.print() 通过类名直接调用。

package demo
// 定义父类 Teacher
open class Teacher {
   public static func print(): Unit {
     println("I am Teacher")
   }
}
// 定义子类 Student,继承自 Teacher
class Student <: Teacher {
   public static func print(): Unit {
     println("I am Student")
   }
}
main() {
  Teacher.print()  //静态函数直接用类名调用
  Student.print() //静态函数直接用类名调用
  }

六、接口继承(6.6)

例6-10 接口定义及 Circle 类的实现

6.6.1:interface Shape 含 area()、getname()、gettitle 属性和 + 操作符,Circle 实现全部成员。

package demo
// 定义一个接口 Shape,要求继承该接口的类实现计算面积的方法
interface Shape {
    // 成员函数:计算面积
    func area(): Float64
    // 成员函数:获取形状的名字
    func getname(): String
    // 成员属性:获取标题
    prop gettitle: String
    // 操作符重载:加法操作,表示合并两个形状的面积
    operator func +(other: Shape): Float64
}
// 定义一个实现了 Shape 接口的类 Circle(圆形)
class Circle <: Shape {
    var radius: Float64
    var name: String
    var title: String
    // Circle的构造函数
    init(radius: Float64, name: String, title: String) {
        this.radius = radius
        this.name = name
        this.title = title
    }
    // 实现接口的成员函数 area
    public func area(): Float64 {
        return 3.14159 * radius * radius
    }
    // 实现接口的成员函数 getname
    public func getname(): String {
        return name
    }
    // 实现接口的成员属性 gettitle
    public prop gettitle: String {
        get() {
            return title
        }
    }
    // 重载加法操作符,合并两个圆形的面积
    public operator func +(other: Shape): Float64 {
        return this.area() + other.area()
    }
}
// 主程序
main(): Int64 {
    // 创建一个圆形实例对象a,并赋给Shape
    let a = Circle(5.0, "圆", "头部")
    let b: Shape=a 
    println(b.area())
    println(b+a)    
    return 0
}

例6-11 接口成员中包含静态成员

6.6.1:Shape 接口增加 static func getnum(),Circle 用静态变量 number 统计实例数量。

package demo
// 定义一个接口 Shape,要求继承该接口的类实现计算面积的方法
interface Shape {
    // 成员函数:计算面积
    func area(): Float64
    // 成员函数:获取形状的名字
    func getname(): String
    // 成员属性:获取标题
    prop gettitle: String
    // 操作符重载:加法操作,表示合并两个形状的面积
    operator func +(other: Shape): Float64
    static func getnum():Int64
}
// 定义一个实现了 Shape 接口的类 Circle(圆形)
class Circle <: Shape {
    var radius: Float64
    var name: String
    var title: String
    static var number:Int64=0
    // Circle的构造函数
    init(radius: Float64, name: String, title: String) {
        this.radius = radius
        this.name = name
        this.title = title
        number++
    }
    // 实现接口的成员函数 area
    public func area(): Float64 {
        return 3.14159 * radius * radius
    }
    // 实现接口的成员函数 getname
    public func getname(): String {
        return name
    }
    // 实现接口的成员属性 gettitle
    public prop gettitle: String {
        get() {
            return title
        }   
    }
    // 重载加法操作符,合并两个圆形的面积
    public operator func +(other: Shape): Float64 {
        return this.area() + other.area()
    }
   
         // 实现接口的成员函数 getnum
    public static func getnum():Int64 {
        return number
    }
}
// 主程序
main(): Int64 {
    // 创建一个圆形实例对象a,并赋给Shape
    let a = Circle(5.0, "圆", "头部")
    println("第${Circle.number}个${a.getname()}面积是${a.area()}")
    let b = Circle(1.0, "圆", "关节")
    println("第${Circle.getnum()}个${b.getname()}面积是${b.area()}")
    println("两部分面积的和${b+a}")
    return 0
}

例6-12 多个类实现同一个接口

6.6.2:Circle 和 Rectangle 均实现 Shape 接口,用 + 操作符合并两种图形的面积。

package demo
// 定义一个接口 Shape,要求继承该接口的类实现计算面积、获取名字和标题等方法
interface Shape {
    // 成员函数:计算面积
    func area(): Float64    
    // 成员函数:获取形状的名字
    func getname(): String    
    // 成员属性:获取形状的标题
    prop gettitle: String    
    // 操作符重载:加法操作,表示合并两个形状的面积
    operator func +(other: Shape): Float64
}

// 定义一个实现了 Shape 接口的类 Circle(圆形)
class Circle <: Shape {
    var radius: Float64
    var name: String
    var title: String    
    // Circle的构造函数
    init(radius: Float64, name: String, title: String) {
        this.radius = radius
        this.name = name
        this.title = title
    }    
    // 实现接口的成员函数 area:计算圆形的面积
    public func area(): Float64 {
        return 3.14159 * radius * radius
    }
    // 实现接口的成员函数 getname:返回圆形的名字
    public func getname(): String {
        return name
    }
    // 实现接口的成员属性 gettitle:返回圆形的标题
    public prop gettitle: String {
        get() {
            return title
        }
    }
    // 实现接口的加法操作符:合并两个圆形的面积
    public operator func +(other: Shape): Float64 {
        return this.area() + other.area()
    }
}
// 定义一个实现了 Shape 接口的类 Rectangle(矩形)
class Rectangle <: Shape {
    var width: Float64
    var height: Float64
    var name: String
    var title: String
    
    // Rectangle的构造函数
    init(width: Float64, height: Float64, name: String, title: String) {
        this.width = width
        this.height = height
        this.name = name
        this.title = title
    }
    // 实现接口的成员函数 area:计算矩形的面积
    public func area(): Float64 {
        return width * height
    }
    // 实现接口的成员函数 getname:返回矩形的名字
    public func getname(): String {
        return name
    }
    // 实现接口的成员属性 gettitle:返回矩形的标题
    public prop gettitle: String {
        get() {
            return title
        }
    }
    // 实现接口的加法操作符:合并两个矩形的面积
    public operator func +(other: Shape): Float64 {
        return this.area() + other.area()
    }
}
// 主程序
main(): Int64 {
    // 创建一个圆形实例和一个矩形实例
    let circle = Circle(5.0, "圆", "头部")
    let rectangle = Rectangle(4.0, 6.0, "矩形", "躯体")    
    // 输出圆形和矩形的面积
    println("${circle.title}${circle.name}的面积是: ${circle.area()}")
    println("${rectangle.title}${rectangle.name}的面积是: ${rectangle.area()}")    
    // 用+重载函数输出面积的和
    let totalArea = circle + rectangle
    println("合并的总面积是: ${totalArea}")    
    return 0
}

例6-13 一个类实现多个接口

6.6.2:MyInt 同时实现 Addable 和 Subtractable 两个接口,支持加法和减法操作。

package demo
// 定义一个可加法操作的接口
interface Addable {
    func add(other: Int64): Int64
}
// 定义一个可减法操作的接口
interface Subtractable {
    func sub(other: Int64): Int64
}
// 定义一个实现了 Addable 和 Subtractable 接口的类
class MyInt <: Addable & Subtractable {
    var value: Int64    
    // 构造函数初始化 value
    init(value: Int64) {
        this.value = value
    }    
    // 实现 Addable 接口的 add 方法
    public func add(other: Int64): Int64 {
        return this.value + other
    }    
    // 实现 Subtractable 接口的 sub 方法
    public func sub(other: Int64): Int64 {
        return this.value - other
    }
}
// 主程序
main() {
    // 创建 MyInt 类的实例
    let myValue = MyInt(10)    
    // 执行加法操作
    let sum = myValue.add(5)
    println("加法结果:${sum}")  // 输出 15    
    // 执行减法操作
    let difference = myValue.sub(3)
    println("减法结果:${difference}")  // 输出 7    
    return 0
}

例6-14 接口继承接口及在派生类中的实现

6.6.2:Calculable 继承 Addable & Subtractable 并增加 mul/div,MyInt 实现全部四则运算。

package demo
// 定义一个加法接口
interface Addable {
    func add(other: Int64): Int64
}
// 定义一个减法接口
interface Subtractable {
    func sub(other: Int64): Int64
}
// 定义一个扩展自 Addable 和 Subtractable 的接口 Calculable,添加乘法和除法操作
interface Calculable <: Addable & Subtractable {
    func mul(other: Int64): Int64
    func div(other: Int64): Int64
}
// 定义实现了 Calculable 接口的类
class MyInt <: Calculable {
    var value: Int64    
    // 构造函数
    init(value: Int64) {
        this.value = value
    }    
    // 实现 Addable 接口的 add 方法
    public func add(other: Int64): Int64 {
        return this.value + other
    }    
    // 实现 Subtractable 接口的 sub 方法
    public func sub(other: Int64): Int64 {
        return this.value - other
    }    
    // 实现 Calculable 接口的 mul 方法
    public func mul(other: Int64): Int64 {
        return this.value * other
    }    
    // 实现 Calculable 接口的 div 方法
    public func div(other: Int64): Int64 {
        if (other != 0) {
            return this.value / other
        } else {
            println("除数不能为零!")
            return 0
        }
    }
}
// 主程序
main() {
    // 创建 MyInt 类的实例
    let myValue = MyInt(10)    
    // 执行加法操作
    let sum = myValue.add(5)
    println("加法结果:${sum}")  // 输出 15    
    // 执行减法操作
    let difference = myValue.sub(3)
    println("减法结果:${difference}")  // 输出 7    
    // 执行乘法操作
    let product = myValue.mul(4)
    println("乘法结果:${product}")  // 输出 40    
    // 执行除法操作
    let quotient = myValue.div(2)
    println("除法结果:${quotient}")  // 输出 5    
    // 测试除数为零
    let divisionByZero = myValue.div(0)
    println("除数为零时:${divisionByZero}")  // 输出 "除数不能为零!" 然后输出 0    
    return 0
}

例6-15 Any 类型示例

6.6.4:自定义 Any 接口,MyInt/MyFloat/MyString 三个 struct 实现 show(),演示多态赋值。

package demo

// 定义 Any 接口
interface Any {
    func show(): String
}

// 为 Int64 显式实现 Any 接口
struct MyInt <: Any {
    var value: Int64
    init(value: Int64) {
        this.value = value
    }

    public func show(): String {
        return "整数值: ${value}"
    }
}

// 为 Float64 显式实现 Any 接口
struct MyFloat <: Any {
    var value: Float64
    init(value: Float64) {
        this.value = value
    }

    public func show(): String {
        return "浮点数值: ${value}"
    }
}

// 为 String 显式实现 Any 接口
struct MyString <: Any {
    var value: String
    init(value: String) {
        this.value = value
    }

    public func show(): String {
        return "字符串值: ${value}"
    }
}

main(): Int64 {
    var any: Any

    any = MyInt(1)
    println(any.show())     // 输出:整数值: 1

    any = MyFloat(2.0)
    println(any.show())     // 输出:浮点数值: 2.0

    any = MyString("hello, world!")
    println(any.show())     // 输出:字符串值: hello, world!

    return 0
}
 

例6-16 在结构体中实现接口

6.6.5:struct Book + struct MyBook <: Printable,结构体也可实现接口并调用接口方法。

package demo
interface Printable {
    // 接口定义一个打印的功能
    func printDetails(): String
}
struct Book {
    var title: String
    var author: String
    var pages: Int64
    init(){
    this.title=""
    this.author=""
    this.pages=0
    }
    init(title: String,author: String,pages: Int64){
    this.title=title
    this.author=author
    this.pages=pages
    }
}
// 结构体实现接口 Printable
struct MyBook <: Printable {
    var book: Book=Book()
    init(b:Book){
    this.book=b
    } // 实现 Printable 接口中的 printDetails 方法
    public func printDetails(): String {
    return "书名: ${book.title}, 作者: ${book.author}, 页数: ${book.pages}"
    }
}
main() {
    // 创建 Book 实例
    let book1=Book("仓颉程序设计", "罗欣", 350)
    let myBook = MyBook(book1)
    // 调用结构体实现的接口方法
    println(myBook.printDetails())
}

例6-17 interface 的 mut 函数

6.6.5:struct Foo 实现 interface I 的 mut func f(),通过接口变量调用不影响原始 struct 值。

package demo
interface I {
mut func f(): Unit
}
struct Foo <: I {
public var v = 0
public mut func f(): Unit {
v += 1
}
}
main() {
var a = Foo()
var b: I = a
b.f()  // Calling 'f' via 'b' cannot modify the value of 'a'
println(a.v) // 0
}

例6-18 struct 中 mut 函数与 let/var 约束

6.6.5:let 声明的 struct 不能调用 mut 方法,var 声明的可以;接口类型是引用语义,let 也可调用。

package demo
interface I {
    mut func f(): Unit
}

struct Foo <: I {
    public var i = 0

    public mut func f(): Unit {
        i += 1
    }
}

main(): Int64 {
    let a = Foo()
    var b = Foo()
    b.f() //  Ok

    let c: I = Foo()
    c.f() //  Ok,接口类型是引用语义

    return 0
}

例6-19 mut 修饰的成员函数引用

6.6.5:接口类型的变量可以获取 mut 函数引用并通过函数引用调用。

package demo

interface I {
    mut func f(): Unit
}

struct Foo <: I {
    var i = 0

    public mut func f(): Unit {
        i += 1
    }
}

main(): Int64 {
    var a = Foo()

  

    var b: I = Foo()
    var fn = b.f  //  Ok: 接口类型可以获取 mut 函数引用

    fn()  // 调用函数引用,等价于 b.f()

    return 0
}

例6-20 mut 函数的相互调用

6.6.5:mut 函数内部可以调用其他 mut 或非 mut 函数,接口默认实现中同理。

package demo

// 定义一个结构体 Foo
struct Foo {
    var i = 0

    // 可变方法 f,内部可以调用 g
    public mut func f(): Unit {
        i += 1
        g() //  Ok: mut 函数可调用非 mut 或 mut 函数
    }

    // g 也必须是 mut,否则不能调用 mut 函数 f
    public mut func g(): Unit {
        f() //  Ok: mut 函数可以调用 mut 函数
    }
}

// 定义一个接口 I
interface I {
    mut func f(): Unit {
        g() //  Ok
    }

    // g 必须是 mut,否则不能调用 f
    mut func g(): Unit {
        f() //  Ok
    }
}

// 主函数入口
main(): Int64 {
    var foo = Foo()
    foo.f()  // 测试 mut 方法调用

    return 0
}

七、属性(6.7)

例6-21 属性使用示例

6.7:class Lqs 用 mut prop b 封装 private var a,访问时触发 getter/setter 并打印提示。

package demo
class Lqs {
    private var a = 0 // 类的私有变量 a
    // 定义一个公开的属性 b,提供 getter 和 setter
    public mut prop b: Int64 {
       // getter:返回 a 的值,并打印 "get"
        get() {
        println("get")
         return a
       }
       // setter:接收一个值并赋给 a,同时打印 "set"
       set(value) {
             println("set")
             a = value
       }
    }
}
main() {
    var x = Lqs() // 创建Lqs类的实例
    let y = x.b + 1 // 访问属性 b,触发 getter,输出 "get"
    x.b = y // 将 y 的值赋给属性 b,触发 setter,输出 "set"
}

例6-22 属性与接口的结合使用

6.7.1:接口 I1 定义 mut prop size,接口 I2 定义 getSize/setSize 函数,类 C 同时实现两者。

package demo

// 定义接口 I1,包含属性 size
interface I1 {
    mut prop size: Int64
}

// 定义接口 I2,包含 getter/setter 函数
interface I2 {
    func getSize(): Int64
    func setSize(value: Int64): Unit
}

// 类 C 同时实现 I1 和 I2 接口
class C <: I1 & I2 {
    private var mySize = 0

    // 实现 I1 中的属性
    public mut prop size: Int64 {
        get() {
            return mySize
        }
        set(value) {
            mySize = value
        }
    }

    // 实现 I2 中的函数
    public func getSize(): Int64 {
        return mySize
    }

    public func setSize(value: Int64): Unit {
        mySize = value
    }
}

// 主程序
main(): Int64 {
    let a: I1 = C()
    a.size = 5
    println(a.size)  // 输出: 5

    let b: I2 = C()
    b.setSize(10)
    println(b.getSize())  // 输出: 10

    return 0
}

例6-23 实例属性与静态属性

6.7.2:class A 含实例属性 x(get 返回 123)和 static 属性 y(get 返回 321),分别用实例名和类名访问。

package demo

class A {
public prop x: Int64 {
get() {
123
}
}
public static prop y: Int64 {
get() {
321
}
}
}
main() {
var a = A()
println(a.x) // 123
println(A.y) // 321
}

例6-24 只读属性(无 setter)

6.7.2:prop i 只定义 get(),不可赋值修改,let 声明的变量配合只读属性确保不可变性。

package demo
class A {
private let value = 0
public prop i: Int64 {
get() {
value
}
}
}
main() {
var x = A()
println(x.i) // OK
// x.i = 1 // Error
}

例6-25 可读写属性(mut prop)

6.7.2:mut prop i 同时定义 get() 和 set(),var 声明的变量可以读取和赋值修改。

package demo

// 定义一个类 A,包含属性 i 和变量 value
class A {
    private var value: Int64 = 0

    public mut prop i: Int64 {
        get() {
            value
        }
        set(v) {
            value = v
        }
    }
}

main(): Int64 {
    var x = A()
    println(x.i)  // 输出:0
    x.i = 1
    println(x.i)  // 输出:1
    return 0
}

八、程序实例(6.8)

实例1 定义继承关系并实现方法重写

Animal → Dog/Cat,override func speak() 实现不同动物的叫声,展示多态调用。

package demo

// 定义基类 Animal
open class Animal {
    protected var name: String

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

    open public func speak(): Unit {
        println("动物叫")
    }
}

// 定义子类 Dog
class Dog <: Animal {
    public init(name: String) {
        super(name)
    }

    public override func speak(): Unit {
        println("汪汪!")
    }
}

// 定义子类 Cat
class Cat <: Animal {
    public init(name: String) {
        super(name)
    }

    public override func speak(): Unit {
        println("喵喵!")
    }
}

// 主函数
main(): Int64 {
    let a: Animal = Dog("小黑")
    let b: Animal = Cat("小花")

    a.speak()  // 输出:汪汪!
    b.speak()  // 输出:喵喵!

    return 0
}

实例2 使用抽象类与重写方法

abstract Shape → Circle/Rectangle,override func area() 计算圆和矩形的面积。

package demo

abstract class Shape {
    open public func area(): Float64
}

class Circle <: Shape {
    var radius: Float64

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

    public override func area(): Float64 {
        return 3.14159 * radius * radius
    }
}

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

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

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

main(): Int64 {
    let s1: Shape = Circle(3.0)
    let s2: Shape = Rectangle(4.0, 5.0)

    println("圆的面积: ${s1.area()}")
    println("矩形的面积: ${s2.area()}")
    return 0
}

实例3 类对象赋值与动态绑定

Employee → Manager,派生类对象赋值给基类变量,print() 根据实际类型动态调用。

package demo

// 定义父类 Employee
open class Employee {
    protected var name: String

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

    open public func print(): Unit {
        println("我是员工 ${name}")
    }
}

// 子类 Manager 显式构造 + 调用 super
class Manager <: Employee {
    public init(name: String) {
        super(name)
    }

    public override func print(): Unit {
        println("我是经理 ${name}")
    }
}

// 主函数
main(): Int64 {
    var e: Employee = Employee("张三")
    e.print()  // 输出:我是员工 张三

    var m: Employee = Manager("李四")
    m.print()  // 输出:我是经理 李四

    return 0
}

实例4 一个类实现多个接口

MyInt 同时实现 Addable 和 Subtractable 接口,演示接口的组合使用。

package demo

interface Addable {
    func add(other: Int64): Int64
}

interface Subtractable {
    func sub(other: Int64): Int64
}

class MyInt <: Addable & Subtractable {
    var value: Int64

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

    public func add(other: Int64): Int64 {
        return value + other
    }

    public func sub(other: Int64): Int64 {
        return value - other
    }
}

main(): Int64 {
    let m = MyInt(100)
    println("加法结果: ${m.add(30)}")
    println("减法结果: ${m.sub(50)}")
    return 0
}

实例5 使用属性(prop)封装成员变量

Counter 类用 mut prop value 封装 private count,getter/setter 打印访问提示。

package demo

class Counter {
    private var count: Int64 = 0

    public mut prop value: Int64 {
        get() {
            println("get")
            return count
        }
        set(v) {
            println("set")
            count = v
        }
    }
}

main(): Int64 {
    var c = Counter()
    let x = c.value  // 调用 getter
    c.value = x + 10 // 调用 setter
    return 0
}

实例6 类模式匹配与图形描述

Shape → Circle/Rectangle,describe() 函数用 match/case 类模式识别图形类型并输出信息。

package demo

// 基类:图形
open class Shape {
    public open func area(): Float64 { 0.0 }
}

// 子类:圆形
class Circle <: Shape {
    public let radius: Float64

    public init(r: Float64) {
        radius = r
    }

    public override func area(): Float64 {
        3.14159 * radius * radius
    }
}

// 子类:矩形
class Rectangle <: Shape {
    public let width: Float64
    public let height: Float64

    public init(w: Float64, h: Float64) {
        width = w
        height = h
    }

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

// 使用类模式识别图形并输出信息
func describe(s: Shape): Unit {
    match (s) {
        case c: Circle =>       // id:Type,绑定变量 c,可访问 Circle 专有成员
            println("圆形,半径 = ${c.radius},面积 = ${c.area()}")
        case _: Rectangle =>    // _:Type,仅判断类型,不绑定变量
            println("矩形,面积 = ${s.area()}")
        case _ =>
            println("未知图形,面积 = ${s.area()}")
    }
}

main(): Int64 {
    let shapes: Array<Shape> = [Circle(5.0), Rectangle(3.0, 4.0), Circle(2.5)]
    for (s in shapes) {
        describe(s)
    }
    return 0
}