浙江传媒学院 · 仓颉面向对象程序设计 · 基于 CangStream 框架构建
浙江传媒学院 · 仓颉面向对象程序设计 · 基于 CangStream 框架构建
7.1.1 子类型关系与子类型多态;7.1.2 子类型的判定(类继承、接口实现、函数类型、永远成立、传递性、类型别名)。本节为理论内容,无独立示例程序。
7.2.1:add 函数分别接受 Int64 和 Float64 参数,编译器根据实参类型选择对应版本。
package demo
// 函数重载示例
func add(a: Int64, b: Int64): Int64 {
return a + b
}
func add(a: Float64, b: Float64): Float64 {
return a + b
}
main() {
let intResult = add(1, 2) // 调用 Int64 类型的 add
let floatResult = add(1.5, 2.5) // 调用 Float64 类型的 add
println("Int result: ${intResult}")
println("Float result: ${floatResult}")
}
7.2.2:Animal → Dog/Cat,父类变量指向子类实例,运行时调用实际类型的 speak()。
package demo
// 定义父类 Animal
open class Animal {
public open func speak() {
println("动物叫声")
}
}
// 定义子类 Dog 继承自 Animal
class Dog <: Animal {
public override func speak() {
println("汪汪")
}
}
// 定义子类 Cat 继承自 Animal
class Cat <: Animal {
public override func speak() {
println("喵喵")
}
}
main() {
// 父类类型的变量可以指向子类实例
let animal1: Animal = Dog() // 通过父类引用指向子类实例 Dog
let animal2: Animal = Cat() // 通过父类引用指向子类实例 Cat
animal1.speak() // 输出: 汪汪 (实际调用 Dog 中的 speak)
animal2.speak() // 输出: 喵喵 (实际调用 Cat 中的 speak)
}
7.2.2:Speaker 接口,Dog/Cat 实现 speak(),接口变量实现多态调用。
package demo
// 定义接口 Speaker
interface Speaker {
func speak(): Unit
}
// 定义类 Dog 实现 Speaker 接口
class Dog <: Speaker {
public func speak() {
println("汪汪")
}
}
// 定义类 Cat 实现 Speaker 接口
class Cat <: Speaker {
public func speak() {
println("喵喵")
}
}
main() {
// 父接口类型的变量可以指向子类实例
let speaker1: Speaker = Dog() // 通过接口引用指向子类实例 Dog
let speaker2: Speaker = Cat() // 通过接口引用指向子类实例 Cat
speaker1.speak() // 输出: 汪汪 (实际调用 Dog 中的 speak)
speaker2.speak() // 输出: 喵喵 (实际调用 Cat 中的 speak)
}
7.3.1:Int8↔Int16、Float32↔Float64、整数↔浮点的显式转换。
package demo
main() {
// 初始化整数类型变量
let a: Int8 = 3
let b: Int16 = 50
// 将 Int8 转换为 Int16
let r1 = Int16(a)
println("The type of r1 is 'Int16', and r1 = ${r1}")
// 将 Int16 转换为 Int8
let r2 = Int8(b)
println("The type of r2 is 'Int8', and r2 = ${r2}")
// 初始化浮点类型变量
let c: Float32 = 1.0
let d: Float64 = 1.123456789
// 将 Float32 转换为 Float64
let r3 = Float64(c)
println("The type of r3 is 'Float64', and r3 = ${r3}")
// 将 Float64 转换为 Float32
let r4 = Float32(d)
println("The type of r4 is 'Float32', and r4 = ${r4}")
// 将整数转换为浮点数
let e: Int64 = 1024
let f: Float64 = 1024.1024
// 将 Int64 转换为 Float64
let r5 = Float64(e)
println("The type of r5 is 'Float64', and r5 = ${r5}")
// 将 Float64 转换为 Int64
let r6 = Int64(f)
println("The type of r6 is 'Int64', and r6 = ${r6}")
}
7.3.1:Rune 字符与 UInt32 Unicode 标量值之间的相互转换。
package demo
main() {
let x: Rune = 'a' // 将字符 'a' 赋值给 x(Rune 类型)
let y: UInt32 = 65 // 将整数 65 赋值给 y(UInt32 类型)
let r1 = UInt32(x) // 将 Rune 类型的 'a' 转换为对应的 Unicode 标量值 97
let r2 = Rune(y) // 将整数 65 转换为对应的字符 'A'
println("The type of r1 is 'UInt32', and r1 = ${r1}") // 输出 r1 的类型和值
println("The type of r2 is 'Rune', and r2 = ${r2}") // 输出 r2 的类型和值
}
7.3.2:用 is 检查变量的运行时类型,返回 Bool 结果。
package demo
main() {
// 定义一些变量
let a: Int64 = 10
let b: Float64 = 3.14
// 使用 is 操作符检查类型
println("${a is Int64}") // 输出 true
println("${a is Float64}") // 输出 false
println("${b is Float64}") // 输出 true
println("${b is Int64}") // 输出 false
}
7.3.2:Base/Derived 类层次中 is 判断,展示父类变量指向子类实例时的类型检测。
package demo
open class Base {
var name: String = " 仓颉编程语言"}
class Derived <: Base {
var age: UInt8 = 3
}
main() {
let a = 1 is Int64
println("1是 'Int64'类型吗? ${a}")
let b = 1 is String
println("1是'String'类型吗? ${b}")
let b1: Base = Base()
let b2: Base = Derived()
var x = b1 is Base
println("b1是'Base'类型? ${x}")
x = b1 is Derived
println("b1是 'Derived'类型? ${x}")
x = b2 is Base
println("b2是'Base'类型? ${x}")
x = b2 is Derived
println("b2是'Derived'类型? ${x}")
}
7.3.2:as 返回 Option 类型,用 match 处理转换成功/失败两种情况。
package demo
// 定义基类和派生类
open class Base {
var name: String = "仓颉编程语言"
}
class Derived <: Base {
var age: UInt8 = 5
}
main() {
// 创建一个Base类型的对象,并将其转换为Derived类型
let b1: Base = Derived()
// 使用 as 操作符进行类型转换
let result = b1 as Derived // 尝试将Base转换为Derived
// 使用match语句判断转换是否成功
match (result) {
case Option.Some(d: Derived) => println("转换成功!${b1.name}${d.age}岁了!") // 转换成功
case Option.None => println("转换失败!") // 转换失败
}
// 示例:试图将Base类型转换为String类型,肯定会失败
let b2: Base = Base()
let result2 = b2 as String // Base无法转换为String
match (result2) {
case Option.Some(s: String) => println("转换成功!字符串内容: ${s}")
case Option.None => println("转换失败!无法将Base类型转换为String")
}
}
7.3.2:先用 is 判断类型,再用 as 安全转换,避免不必要的失败分支。
// ⚠ 无法读取文件: chapter07/demo7-9
// 错误: The file does not exist or permission denied!
7.4:自定义 Option
package demo
// 定义 Option 类型
enum Option<T> {
Some(T) |
None
}
// 定义泛型类 List,T 为类型形参
class List<T> {
var elem: Option<T>
var tail: Option<List<T>>
List(elem: T, tail: Option<List<T>>) {
this.elem = Option.Some(elem)
this.tail = tail
}
}
// 定义一个函数 sumInt,它接受一个 List<Int64> 类型的参数
func sumInt(a: List<Int64>): Int64 {
var sum: Int64 = 0
var current = a
// 遍历链表中的每个元素并计算总和
while (true) {
match (current.elem) {
case Option.Some(value) => sum += value
case Option.None => break // 不会发生,但如果有空值则退出
}
// 获取下一个节点
match (current.tail) {
case Option.Some(next) => current = next
case Option.None => break // 没有尾部时结束
}
}
return sum
}
main() {
// 创建一个 List<Int64> 类型的链表
let list1 = List<Int64>(1, Option.None)
let list2 = List<Int64>(2, Option.Some(list1))
let list3 = List<Int64>(3, Option.Some(list2))
// 调用 sumInt 计算链表中的元素和
let result = sumInt(list3)
println("The sum of the list is: ${result}") // 输出:The sum of the list is: 6
}
7.4.1:composition 复合两个函数,times2 和 plus10 组合后对输入先乘再加。
package demo
// 定义泛型函数 composition,复合两个函数
func composition<T1, T2, T3>(f: (T1) -> T2, g: (T2) -> T3): (T1) -> T3 {
return {x: T1 => g(f(x))}
}
// 定义两个函数
func times2(a: Int64): Int64 {
return a * 3
}
func plus10(a: Int64): Int64 {
return a + 10
}
// 定义一个函数,复合 times2 和 plus10
func times2plus10(a: Int64):Int64 {
return composition<Int64, Int64, Int64>(times2, plus10)(a)
}
main() {
println(times2plus10(9)) // 输出 37
return 0
}
7.4.1:函数内定义局部泛型函数 id
package demo
func foo(a: Int64):Bool{
// 定义一个局部泛型函数 id
func id<T>(a: T):T {
return a
}
// 定义一个函数 double,返回 a 的两倍
func double(a: Int64):Int64 {
return a + a
}
return (id<Int64> ~> double)(a) == (double ~> id<Int64>)(a)
}
main() {
println(foo(1)) // 输出 true
return 0
}
7.4.1:class A、struct B、enum C 各定义泛型成员函数,要求 T <: ToString。
package demo
class A {
// 定义一个泛型成员函数 foo,要求 T 必须符合 ToString 协议
func foo<T>(a: T) where T <: ToString {
println("${a}")
}
}
struct B {
// 定义一个泛型成员函数 bar,要求 T 必须符合 ToString 协议
func bar<T>(a: T) where T<: ToString {
println("${a}")
}
}
enum C {
X|Y
// 定义一个泛型成员函数 coo,要求 T 必须符合 ToString 协议
func coo<T>(a: T): Unit where T <: ToString {
println("${a}")
}
}
main() {
var a = A()
var b = B()
var c = C.X
// 调用泛型成员函数
a.foo(10) // 输出 10
b.bar("abc") // 输出 abc
c.coo(true) // 输出 true
return 0
}
7.4.1:extend Int64 添加 printIntAndArg
package demo
extend Int64 {
func printIntAndArg<T>(a: T) where T <: ToString {
println(this)
println("${a}")
}
}
main() {
var a: Int64 = 12
a.printIntAndArg<String>("twelve") }
7.4.1:ToPair 类的 static func fromArray
package demo
import std.collection.*
class ToPair {
// 定义一个静态泛型函数 fromArray,返回一个元组
public static func fromArray<T>(l: ArrayList<T>):(T, T) {
return (l[0], l[1])
}
}
main() {
var res: ArrayList<Int64> = ArrayList([1, 2, 3, 4])
var pair: (Int64, Int64) = ToPair.fromArray<Int64>(res) // 调用静态泛型函数
println("(${pair[0]}, ${pair[1]})") // 输出 (1, 2)
return 0
}
7.4.2:Iterable
package demo
// 定义 Iterable 接口
public interface Iterable<E> {
func iterator(): Iterator<E> // 需要实现的函数
}
// 定义 Iterator 接口
public interface Iterator<E> <: Iterable<E> {
func next(): Option<E> // 需要实现的函数
}
// 实现 List 类型,它是一个容器类,并实现 Iterable 接口
class List<T> <: Iterable<T> {
var elements: Array<T> // 内部存储元素
init(elements: Array<T>) {
this.elements = elements
}
// 实现 Iterable 接口的 iterator 方法
public func iterator(): Iterator<T> {
return ListIterator<T>(this) // 返回 ListIterator 实例
}
}
// 实现 ListIterator 类型,它是一个 Iterator
class ListIterator<T> <: Iterator<T> {
var list: List<T>
var currentIndex: Int64 = 0
init(list: List<T>) {
this.list = list
}
// 实现 Iterator 接口的 next 方法
public func next(): Option<T> {
if (this.currentIndex < this.list.elements.size) {
let value = this.list.elements[this.currentIndex]
this.currentIndex += 1
return Option.Some(value) // 返回当前值
} else {
return Option.None // 如果没有更多元素,返回 None
}
}
}
main() {
// 创建一个 List 实例
var myList = List<Int64>([1, 2, 3, 4, 5])
// 获取 List 的 Iterator
var iterator = myList.iterator()
// 使用 iterator 遍历 List 中的元素
while (true) {
match (iterator.next()) {
case Option.Some(value) =>
println("Next value: ${value}")
case Option.None =>
println("End of list")
break
}
}
}
7.4.3:Node
package demo
// 定义泛型类 Node,K 是键类型,V 是值类型
public open class Node<K, V> where K <: Hashable & Equatable<K> {
// 定义键和值,使用 Option 来存储它们
public var key: Option<K> = Option<K>.None
public var value: Option<V> = Option<V>.None
// 默认构造函数
public init() {}
// 带键和值的构造函数
public init(key: K, value: V) {
this.key = Option<K>.Some(key)
this.value = Option<V>.Some(value)
}
}
main() {
// 创建一个 Node 类型实例,键为 Int64 类型,值为 String 类型
let node1 = Node<Int64, String>(123, "Hello")
// 输出节点的键和值
match (node1.key) {
case Option.Some(k) => println("Key: ${k}")
case Option.None => println("Key: None")
}
match (node1.value) {
case Option.Some(v) => println("Value: ${v}")
case Option.None => println("Value: None")
}
// 创建另一个 Node 类型实例,键为 String 类型,值为 Int64 类型
let node2 = Node<String, Int64>("age", 30)
// 输出节点的键和值
match (node2.key) {
case Option.Some(k) => println("Key: ${k}")
case Option.None => println("Key: None")
}
match (node2.value) {
case Option.Some(v) => println("Value: ${v}")
case Option.None => println("Value: None")
}
}
7.4.4:struct Pair
package demo
// 定义一个结构体 Pair,接受两个类型形参 T 和 U
struct Pair<T, U> {
let x: T // 第一个元素
let y: U // 第二个元素
// 构造函数,用于初始化 Pair 的值
public init(a: T, b: U) {
x = a
y = b
}
// 第一个元素
public func first(): T {
return x
}
// 第二个元素
public func second(): U {
return y
}
}
main() {
// 创建一个 Pair 实例,类型为 Pair<String, Int64>
var a: Pair<String, Int64> = Pair<String, Int64>("hello", 0)
// 输出 Pair 中的第一个和第二个元素
println(a.first()) // 输出 "hello"
println(a.second()) // 输出 0
}
7.4.5:自定义 Option
package demo
public enum Option<T> {
| Some(T) // Some 包装了类型 T 的值
| None // 表示没有值
// 获取 Option 中的值,如果是 Some,则返回其内部的值,否则抛出异常
public func getOrThrow(): T {
match (this) {
case Some(v) => v
case None => throw NoneValueException() // 如果是 None,则抛出异常
}
}
}
// 安全的除法函数
func safeDiv(a: Int64, b: Int64): Option<Int64> {
var res: Option<Int64> = match (b) {
case 0 => None // 除数为 0 时返回 None
case _ => Some(a / b) // 否则返回 Some(a / b)
}
return res
}
main() {
// 测试安全除法
let result1 = safeDiv(10, 2)
match (result1) {
case Some(value) => println("The result is: ${value}") // 输出除法结果
case None => println("Division by zero!") // 输出错误信息
}
let result2 = safeDiv(10, 0)
match (result2) {
case Some(value) => println("The result is: ${value}") // 不会执行
case None => println("Division by zero!") // 输出错误信息
}
}
7.4.7:type RD
package demo
struct RecordData<T> {
var a: T
public init(x: T){
a = x
}
}
type RD<T> = RecordData<T>
main(): Int64 {
var struct1: RD<Int32> = RecordData<Int32>(2)
return 0
}
7.4.8:genericPrint
package demo
import std.core.*
//定义一个名为 genericPrint 的函数泛型类型 T 实现 ToString 接口
func genericPrint<T>(a: T) where T <:ToString {
println(a)
}
main() {
genericPrint<Int64>(100) // 100 会被转为字符串并打印
return 0
}
// 以下是错误示例:
// package demo
// import std.core.*
// //定义一个名为 genericPrint 的函数泛型类型 T 实现 ToString 接口
// func genericPrint<T>(a: T) where T <:ToString {
// println(a)
// }
// main():Int64 {
// genericPrint<(Int64) -> Int64>({ i => 0 })
// return 0
// }
7.4.8:Zoo
package demo
import std.collection.*
abstract class Animal {
public func run(): String
}
class Dog <: Animal {
public func run(): String {
return "dog run"
}
}
class Fox <: Animal {
public func run(): String {
return "fox run"
}
}
class Zoo<T> where T <: Animal {
var animals: ArrayList<Animal> = ArrayList<Animal>()
public func addAnimal(a: T) {
animals.add(a)
}
public func allAnimalRuns() {
for (a in animals) {
println(a.run()) // 这里的 `run` 方法要求 `T` 必须是 `Animal` 的子类
}
}
}
main() {
var zoo: Zoo<Animal> = Zoo<Animal>()
zoo.addAnimal(Dog()) // 添加 Dog 到动物园
zoo.addAnimal(Fox()) // 添加 Fox 到动物园
zoo.allAnimalRuns() // 输出所有动物的跑步动作
}
7.5.2:extend Int64 添加 square() 返回平方值,直接用 num.square() 调用。
package demo
// 定义一个扩展来为 Int64 类型添加一个新函数
extend Int64 {
// 添加一个新函数:返回该数字的平方
func square(): Int64 {
return this * this
}
}
// 使用扩展的功能
main() {
var num: Int64 = 5
println(num.square()) // 输出:25
return 0
}
7.5.2:extend String 添加 printSize() 输出字符串长度。
package demo
// 定义一个扩展来为String 类型添加一个新函数printSize
extend String {
public func printSize() {
println("the size is ${this.size}")
}
}
// 使用扩展的功能
main() {
let a = "123"
a.printSize() // the size is 3
}
7.5.2:extend Pair
package demo
class Pair<T1, T2> {
var first: T1
var second: T2
public init(a: T1, b: T2) {
first = a
second = b
}
}
interface Eq<T> {
func equals(other: T): Bool
}
// 扩展 Pair<T1, T2> 类型,增加 equals 功能,前提是 T1 和 T2 都实现 Eq 接口
extend<T1, T2> Pair<T1, T2> where T1 <: Eq<T1>, T2 <: Eq<T2> {
public func equals(other: Pair<T1, T2>) {
first.equals(other.first) && second.equals(other.second)
}
}
// 实现 Eq 接口的类 Foo
class Foo <: Eq<Foo> {
public func equals(other: Foo): Bool {
return true
}
}
// 使用扩展的 Pair 类型
main() {
let a = Pair(Foo(), Foo())
let b = Pair(Foo(), Foo())
println(a.equals(b)) // 输出:true
}
7.5.3:extend Array
package demo
interface PrintSizeable {
func printSize(): Unit
}
extend<T> Array<T> <: PrintSizeable {
public func printSize() {
println("The size is ${this.size}")
}
}
main() {
let a: PrintSizeable = Array<Int64>()
a.printSize() // 输出: The size is 0
}
area 函数三个重载版本:圆(Float64 半径)、矩形(长×宽)、正方形(边长)。
package demo
// 计算不同图形的面积:函数重载
func area(radius: Float64): Float64 {
return 3.14 * radius * radius
}
func area(length: Int64, width: Int64): Int64 {
return length * width
}
func area(side: Int64): Int64 {
return side * side
}
main() {
println("圆面积: ${area(3.0)}")
println("矩形面积: ${area(4, 5)}")
println("正方形面积: ${area(6)}")
}
Shape → Circle/Rectangle,override func draw() 实现不同图形的绘制。
package demo
open class Shape {
public open func draw() {
println("绘制图形")
}
}
class Circle <: Shape {
public override func draw() {
println("绘制圆形")
}
}
class Rectangle <: Shape {
public override func draw() {
println("绘制矩形")
}
}
main() {
let s1: Shape = Circle()
let s2: Shape = Rectangle()
s1.draw()
s2.draw()
}
Person/Student 类层次,is 判断 + as 转换,match 处理成功与失败分支。
package demo
open class Person {
var name: String = "未知"
}
class Student <: Person {
var grade: Int64 = 1
}
main() {
let p1: Person = Student()
// 使用 is 判断
if (p1 is Student) {
println("p1是学生类型")
}
// 使用 as 转换
let result = p1 as Student
match(result) {
case Option.Some(s: Student) => println("转换成功,年级=${s.grade}")
case Option.None => println("转换失败")
}
}
Box
package demo
// 定义泛型容器
class Box<T> {
var value: T
public init(v: T) { value = v }
public func get(): T { return value }
}
// 泛型函数
func swap<T>(a: T, b: T): (T, T) {
return (b, a)
}
main() {
let intBox = Box<Int64>(100)
let strBox = Box<String>("Hello")
println("intBox: ${intBox.get()}")
println("strBox: ${strBox.get()}")
let res = swap<String>("A", "B")
println("交换结果: (${res[0]}, ${res[1]})")
}
extend String 添加 wordCount() 方法,按空格分词统计单词数量。
package demo
// 为 String 扩展一个新方法:按空格分词统计单词数
extend String {
public func wordCount(): Int64 {
var count: Int64 = 0
var inWord: Bool = false
// 逐字节扫描;注意使用字节字面量 b' ' 作为空格
for (b in this) {
if (b == b' ') {
if (inWord) {
inWord = false
}
} else {
if (!inWord) {
count = count + 1 // 避免复合自增带来的类型推断问题
inWord = true
}
}
}
return count
}
}
main(): Int64 {
let s = "Hello Cangjie Language"
println("原字符串: '${s}'")
println("单词数量: ${s.wordCount()}")
return 0
}