浙江传媒学院 · 仓颉面向对象程序设计 · 基于 CangStream 框架构建
浙江传媒学院 · 仓颉面向对象程序设计 · 基于 CangStream 框架构建
5.1.1:struct Point 含两个 init 构造,展示结构体作为类实现的起点。
package demo
struct Point {
let x: Int64
let y: Int64
public init() {
x=50
y=100
}
public init(a:Int64,b:Int64) {
x=a
y=b
}
}
main(): Int64 {
var a=Point()
var b=Point(5,10)
println(" 点a的坐标为:(${a.x},${a.y})")
println(" 点b的坐标为:(${b.x},${b.y})")
return 0
}
5.1.2:class Hanzi 含 radical/component 两个 String 字段和 compose() 成员函数。
package demo
class Hanzi {
let radical: String
let component: String
public init(radical: String, component: String) {
this.radical = radical
this.component = component
}
public func compose(): String {
return radical + component
}
}
// 示例使用
main() {
let h = Hanzi("氵", "青") // 比如“清”字的组合
let fullChar = h.compose()
println("${fullChar}由${h.radical}与${h.component}两部分组成")
}
5.2.1:static var num=0 内联设置初始值,每次构造自动 num++,Hanzi.num 访问。
package demo
class Hanzi {
let radical: String
let component: String
static var num=0
public Hanzi(radical: String, component: String) {
this.radical = radical
this.component = component
num++
}
public func compose(): String {
return radical + component
}
}
main() {
let h1 = Hanzi("氵", "青")
let fullChar1 = h1.compose()
println("第${Hanzi.num}个汉字的组合是:${fullChar1}")
let h2 = Hanzi("氵", "王")
let fullChar2 = h2.compose()
println("第${Hanzi.num}个汉字的组合是:${fullChar2}")
}
5.2.1:static var num: Int64 不内联赋值,在 static init() 块中显式初始化为 0。
package demo
class Hanzi {
let radical: String
let component: String
static var num:Int64
static init(){
num=0
}
public init(radical: String, component: String) {
this.radical = radical
this.component = component
num++
}
public func compose(): String {
return radical + component
}
}
5.3:class Student 含 score 属性(get/set 验证范围)和 grade 只读属性(转换成绩等级)。
package demo
class Student {
var studentId: String=""
var name: String=""
var age: Int=0
private var internalScore: Float64 = 0.0
public mut prop score: Float64 {
get() {
return internalScore
}
set(value) {
if (value >= 0.0 && value <= 100.0) {
internalScore = value
}
}
}
public prop grade: String {
get() {
if (this.score >= 90.0) {return "A"}
if (this.score >= 80.0) {return "B"}
if (this.score >= 70.0) {return "C"}
if (this.score >= 60.0) {return "D"}
return "还没有录入成绩!"
}
}
}
main() {
let stdent = Student()
println(stdent.grade)
}
5.3.1:普通构造函数重载,分别支持零参、单参(偏旁=部首)、双参三种创建方式。
package demo
class Hanzi {
let radical: String
let component: String
static var num=0
public init(){
this.radical="氵"
this.component="永"
num++
}
public init(radical: String){
this.radical=radical
this.component=radical
num++
}
public init(radical: String, component: String) {
this.radical = radical
this.component = component
num++
}
public func compose(): String {
return radical + component
}
}
main() {
let h1 =Hanzi()
let fullChar1 = h1.compose()
println("第${Hanzi.num}个汉字的组合是:${fullChar1}")
let h2 = Hanzi("木")
let fullChar2 = h2.compose()
println("第${Hanzi.num}个汉字的组合是:${fullChar2}")
let h3 = Hanzi("氵","木")
let fullChar3 = h3.compose()
println("第${Hanzi.num}个汉字的组合是:${fullChar3}")
}
5.3.2:Student(var studentId, var name, var age, var internalScore) 主构造函数语法,字段与参数同名自动绑定。
package demo
class Student {
Student(var studentId: String,var name: String,var age: Int,var internalScore: Float64){
this.studentId=studentId
this.name=name
this.age=age
this.internalScore=internalScore
}
public mut prop score: Float64 {
get() {
return internalScore
}
set(value) {
if (value >= 0.0 && value <= 100.0) {
internalScore = value
}
}
}
public prop grade: String {
get() {
if (this.score >= 90.0) {return "A"}
if (this.score >= 80.0) {return "B"}
if (this.score >= 70.0) {return "C"}
if (this.score >= 60.0) {return "D"}
return "还没有录入成绩!"
}
}
}
main() {
let student = Student("250101","李晓泓",25,90.6)
println(student.grade)
}
5.3.2:同时定义 init()(无参)和 Time(h, m, s)(主构造),演示两者共存与调用。
package demo
class Time {
private var hour: Int64
private var minute: Int64
private var second: Int64
// 普通构造器
public init() {
this.hour = 0
this.minute = 0
this.second =0
}
// 主构造器
public Time(h: Int64, m: Int64, s: Int64) {
this.hour = h
this.minute = m
this.second = s
}
// 设置时间
public func setTime(h: Int64, m: Int64, s: Int64): Unit {
this.hour = h
this.minute = m
this.second = s
}
// 显示时间
public func showTime(): Unit {
println("${hour}.${minute}.${second}")
}
}
main(): Int64 {
var t = Time() //调用普通构造器
println("初始时间:")
t.showTime()
println("第一次更新后的时间:")
t=Time(8, 15, 0)
t.showTime()
println("第二次更新后的时间:")
t.setTime(14, 5, 0)
t.showTime()
return 0
}
5.3.2:仅保留 Time(var hour, var minute, var second){},体现主构造函数的最简形式。
package demo
class Time {
public Time( var hour: Int64, var minute: Int64, var second: Int64) {}
public func setTime(h: Int64, m: Int64, s: Int64): Unit {
this.hour = h
this.minute = m
this.second = s
}
// 显示时间
public func showTime(): Unit {
println("${hour}.${minute}.${second}")
}
}
main(): Int64 {
var t = Time(0, 0, 0) //调用主构造器(初始化为零时刻)
println("初始时间:")
t.showTime()
println("第一次更新后的时间:")
t=Time(8, 15, 0)
t.showTime()
println("第二次更新后的时间:")
t.setTime(14, 5, 0)
t.showTime()
return 0
}
5.4.1:Hanzi 含 character/radical/component 三字段,display() 格式化输出组合关系。
package demo
class Hanzi{
Hanzi(var character :String,var radical: String, var component: String){
this.character=character
this.radical=radical
this.component=component
}
public func display() {
println("${character}=${radical}+${component}")
}
}
main() {
let h1 =Hanzi("清","氵","青")
let h2 =Hanzi("江","氵","工")
let h3 =Hanzi("汪","氵","王")
let hanziList: Array<Hanzi> = [h1, h2, h3]
for (h in hanziList) {
h.display()
}
}
5.4.2:public static func typeName() 只能通过类名调用,不能访问实例字段。
package demo
class Hanzi {
public Hanzi(var radical: String, var component: String ){}
static var num=0
public init(){
this.radical="氵"
this.component="永"
num++
}
public static func typeName(): String { "泳" }
public func compose(): String {
return typeName()+"="+radical +"+"+ component
}
}
main() {
let h1 = Hanzi()
println("第${Hanzi.num}个:${h1.compose()}")
}
5.4.1:private var x/y 隐藏实现细节,通过 setPoint、getx、gety 提供受控访问。
package demo
class Point {
private var x: Int64 = 0
private var y: Int64 = 0
// 设置点的坐标
public func setPoint(a: Int64, b: Int64): Unit {
this.x = a
this.y = b
}
// 获取x坐标
public func getx(): Int64 {
return this.x
}
// 获取y坐标
public func gety(): Int64 {
return this.y
}
}
main(): Int64 {
// 创建一个Point对象
let obja = Point()
// 调用setPoint初始化坐标
obja.setPoint(100, 200)
// 读取坐标并输出
let i = obja.getx()
let j = obja.gety()
println("obja i=${i} obja j=${j}")
return 0
}
5.6:构造时 mallocCString 分配 CString 资源,~init() 终结器自动释放,演示 RAII 模式。
package demo
class Circle {
var name: CString // 圆的名称
let radius: Float64
// 构造函数:分配CString资源
public init(r: Float64, label: String) {
radius = r
name = unsafe { LibC.mallocCString(label) }
println("创建圆:${label},半径=${r}")
}
// 终结器:释放系统资源
~init() {
unsafe { LibC.free(name) }
println("释放圆的资源")
}
// 计算面积
public func area(): Float64 {
3.14* radius * radius
}
}
main() {
let c = Circle(5.0, "单位圆")
println("面积=${c.area()}")
// 块结束,c 被销毁,此时自动调用 ~init()
}
5.7.1:用 . 运算符调用成员函数,演示通过公有方法访问私有字段的封装模式。
package demo
class Point {
private var x: Int64 = 0
private var y: Int64 = 0
// 设置点的坐标
public func setPoint(a: Int64, b: Int64): Unit {
this.x = a
this.y = b
}
// 获取x坐标
public func getx(): Int64 {
return this.x
}
// 获取y坐标
public func gety(): Int64 {
return this.y
}
}
main(): Int64 {
// 创建一个Point对象
let obja = Point()
// 调用setPoint初始化坐标
obja.setPoint(100, 200)
// 读取坐标并输出
let i = obja.getx()
let j = obja.gety()
println("obja i=${i} obja j=${j}")
return 0
}
5.7.3:private var x、protected var y、public var z 三种访问级别,展示可见性差异。
package demo
class Data {
private var x: Int64 = 0 // 私有变量
protected var y: Int64 = 0 // 受保护变量
public var z: Int64 = 0 // 公有变量
// 公有函数:设置数据
public func setData(a: Int64, b: Int64, c: Int64): Unit {
this.x = a
this.y = b
this.z = c
}
// 公有访问器函数
public func getx(): Int64 {
return this.x
}
public func gety(): Int64 {
return this.y
}
public func getz(): Int64 {
return this.z
}
}
main(): Int64 {
let obj = Data()
obj.setData(1, 2, 3)
println("obj.x=${obj.getx()}") // 通过公有函数访问私有成员
println("obj.y=${obj.gety()}") // 通过公有函数访问受保护成员
println("obj.z=${obj.z}") // 直接访问公有成员
return 0
}
5.8.1:Point 带静态计数器 n,构造时递增,展示点的坐标和两点之间的欧氏距离。
package demo
import std.math.*
class Point {
let x: Int64
let y: Int64
static var n=0
init(x: Int64, y: Int64) {
this.x = x
this.y = y
n++
}
func distance(topoint: Point):Float64 {
let dx=Float64(x - topoint.x)
let dy=Float64( y - topoint.y)
return Float64(sqrt(dx*dx+dy*dy)) // 计算两点间的欧氏距离
}
}
main(): Int64 {
let a =Point(10,20)
println(" 第${Point.n}个点的坐标是:(${a.x},${a.y})")
var b =Point(100,200)
println(" 第${Point.n}个点的坐标是:(${b.x},${b.y})")
let dis=Int64(a.distance(b))
println(" 两点之间的距离是:(${dis})")
return 0
}
5.8.2:用 Array[Point] 保存多个点对象,含默认构造和带参构造,计算两点距离。
package demo
import std.math.*
class Point {
static var n: Int64 =0 // 静态变量:记录点的个数
var x: Float64
var y: Float64
public init() {
this.x = 0.0
this.y = 0.0
}
public init(x: Float64, y: Float64) {
this.x = x
this.y = y
Point.n++
}
// 成员函数:计算与另一点之间的距离
public func distance(p: Point): Float64 {
let dx = this.x - p.x
let dy = this.y - p.y
return sqrt(dx * dx + dy * dy)
}
}
// 主函数
main(): Int64 {
// 用(0,0)作为第一个默认点,创建一个点数组,初始有两个点
var pts: Array<Point> = [ Point(10.0, 20.0), Point() ]
println("默认点的坐标是:(${Int64(pts[1].x)},${Int64(pts[1].y)})")
println("第${Point.n}个点的坐标:(${Int64(pts[0].x)},${Int64(pts[0].y)})")
// 计算两点之间的距离
var dis = pts[0].distance(pts[1])
println("两点之间的距离是:${Int64(dis)}")
return 0
}
5.8.3:class Line 以两个 Point 对象为成员,length() 调用 Point.distance() 计算线段长度。
package demo
import std.math.*
// 点类定义
class Point {
var x: Int64
var y: Int64
public init(x: Int64, y: Int64) {
this.x = x
this.y = y
}
public func print() {
println("(${x}, ${y})")
}
func distance(topoint: Point):Float64 {
let dx=Float64(x - topoint.x)
let dy=Float64( y - topoint.y)
return (sqrt(dx*dx+dy*dy)) // 计算两点间的欧几里得距离
}
}
// 直线类,包含两个点
class Line {
var start: Point
var end: Point
public init(start: Point, end: Point) {
this.start = start
this.end = end
}
// 打印起点和终点
public func print() {
print("直线起点:")
start.print()
print("直线终点:")
end.print()
}
// 计算线段长度
public func length(): Float64 {
return start.distance(end)
}
}
main(): Int64 {
// 创建两个点对象
let p1 = Point(1, 2)
let p2 = Point(4, 6)
// 使用点对象构建直线对象
let line = Line(p1, p2)
// 打印直线信息
line.print()
// 输出线段长度
let len = line.length()
println("直线长度为:${len}")
return 0
}
5.8.4:obj2 = obj1 使两个变量指向同一对象,修改任一方向对方的字段同步改变。
package demo
class Point {
private var x: Int64 = 0
private var y: Int64 = 0
// 设置点坐标
public func setPoint(a: Int64, b: Int64): Unit {
this.x = a
this.y = b
}
// 显示坐标
public func show(): Unit {
println("${x} ${y}")
}
}
main(): Int64 {
var obj1 = Point()
var obj2 = Point()
obj1.setPoint(1, 2)
obj2 = obj1 // 对象赋值(引用复制)
obj1.show()
obj2.show()
return 0
}
5.9.1:成员函数内的 x 直接引用本类成员变量,无需 this;外部通过实例名访问。
package demo
class Abc {
public var x: Int64 = 0
// 设置成员变量 x
public func set(a: Int64): Unit {
this.x = a
}
// 显示 x
public func show(): Unit {
println("x=${x}")
}
}
main(): Int64 {
let obj = Abc()
obj.set(2)
obj.show()
obj.x = 3
obj.show()
return 0
}
5.9.2:this 指针指向当前对象,static counter 记录创建顺序,this.id 存储唯一编号。
package demo
class Finger {
private var x: Int64
private var id: Int64 // 模拟唯一标识(this 指针)
// 静态计数器
static var counter: Int64 = 0
// 构造函数
public init(x1: Int64) {
this.x = x1
Finger.counter++
this.id = Finger.counter
}
public func disp(): Unit {
println("this=对象${id} when x=${x}")
}
}
main(): Int64 {
let a = Finger(1)
let b = Finger(2)
let c = Finger(3)
a.disp()
b.disp()
c.disp()
return 0
}
Hanzi 类封装偏旁/部首(private),static totalCount 统计总数,getInfo() 格式化输出组合信息。
package demo
class Hanzi {
private let radical: String // 使用private访问控制,提高封装性
private let component: String
static var totalCount: Int64 = 0 // 静态变量用于统计汉字总数
public init(radical: String, component: String) { // 构造函数
this.radical = radical
this.component = component
Hanzi.totalCount++
}
public func compose(): String {// 组合汉字方法
return "${radical}${component}"
}
public func getRadical(): String {// 获取偏旁
return radical
}
public func getComponent(): String {// 获取部首
return component
}
public static func getTotalCount(): Int64 { // 静态方法获取总数
return totalCount
}
public static func resetCount(): Unit { // 重置计数器(重新开始统计)
totalCount = 0
}
public func getInfo(): String {// 获取汉字信息的详细描述
return "偏旁「${radical}」+ 部首「${component}」→ 汉字「${compose()}」"
}
}
main() {
let h1 = Hanzi("氵", "青")
let h2 = Hanzi("亻", "言")
let h3 = Hanzi("口", "马")
println("组合的汉字有:")
println(h1.getInfo())
println(h2.getInfo())
println(h3.getInfo())
println("共组合了${Hanzi.totalCount}个汉字")
}
Point(坐标+距离)作为 Line 的成员,line.print() 输出起终点,line.length() 计算线段长度。
package demo
import std.math.*
// 点类定义
class Point {
public let x: Int64
public let y: Int64
public init(x: Int64, y: Int64) {
this.x = x
this.y = y
}
public func print() {
println("(${x}, ${y})")
}
func distance(topoint: Point): Float64 {
let dx = Float64(x - topoint.x)
let dy = Float64(y - topoint.y)
return sqrt(dx*dx + dy*dy)
}
}
// 直线类,包含两个点
class Line {
var start: Point
var end: Point
public init(start: Point, end: Point) {
this.start = start
this.end = end
}
// 打印起点和终点
public func print() {
print("直线起点:")
start.print()
print("直线终点:")
end.print()
}
// 计算线段长度
public func length(): Float64 {
return start.distance(end)
}
}
main(): Int64 {
let p1 = Point(0, 0)
let p2 = Point(3, 4)
let line = Line(p1, p2)
line.print()
let len = line.length()
println("直线长度为:${len}")
return 0
}
Array[Point] 管理点集,循环输出各点坐标及相邻两点距离,综合展示对象数组的使用。
package demo
import std.math.*
class Point {
public let x: Float64
public let y: Float64
public init(x: Float64, y: Float64) {
this.x = x
this.y = y }
public init(x: Int64, y: Int64) {
this.x = Float64(x)
this.y = Float64(y)
}
// 计算到另一点的距离
public func distanceTo(other: Point): Float64 {
let dx = this.x - other.x
let dy = this.y - other.y
return sqrt(dx * dx + dy * dy)
}
public func toString(): String {
return "(${Int64(x)}, ${Int64(y)})"
}
}
main() {
let pts: Array<Point> = [ Point(1, 2), Point(3, 4), Point(5, 6) ]
for (i in 0..pts.size-1) {
print("第${i+1}个点的坐标:")
println("${pts[i].toString()}")
println("第${i+1}个点与第${i+2}个点的距离是:${pts[i].distanceTo(pts[i+1])}")
}
print("第${pts.size}个点的坐标:")
println("${pts[pts.size-1].toString()}")
}
Time 类含 hour/minute/second 三字段,show() 展示当前时间,setTime() 修改时间值。
package demo
class Time {
var hour: Int64
var minute: Int64
var second: Int64
public init(h: Int64, m: Int64, s: Int64) {
this.hour = h
this.minute = m
this.second = s
}
public func show(): Unit {
println("时间是:${hour}:${minute}:${second}")
}
public func setTime(h: Int64, m: Int64, s: Int64): Unit {
this.hour = h
this.minute = m
this.second = s
}
}
main(): Int64 {
let t = Time(8, 30, 0)
t.show()
t.setTime(14, 45, 30)
t.show()
return 0
}
enum Quadrant 定义七种位置(四象限/原点/X轴/Y轴),Point.getInfo() 用 match 给出点的坐标与位置描述。
package demo
// 枚举定义象限
enum Quadrant {
| First // 第一象限 (+,+)
| Second // 第二象限 (-,+)
| Third // 第三象限 (-,-)
| Fourth // 第四象限 (+,-)
| Origin // 原点
| XAxis // X轴
| YAxis // Y轴
}
class Point {
public let x: Float64
public let y: Float64
public init(x: Float64, y: Float64) {
this.x = x
this.y = y }
public init(x: Int64, y: Int64) {
this.x = Float64(x)
this.y = Float64(y)
}
// 判断点所在象限
public func getQuadrant(): Quadrant {
if (x == 0.0 && y == 0.0) { return Quadrant.Origin }
if (x == 0.0) { return Quadrant.YAxis }
if (y == 0.0) { return Quadrant.XAxis }
if (x > 0.0 && y > 0.0) { return Quadrant.First }
if (x < 0.0 && y > 0.0) { return Quadrant.Second }
if (x < 0.0 && y < 0.0) { return Quadrant.Third }
return Quadrant.Fourth
}
public func toString(): String {
return "(${Int64(x)}, ${Int64(y)})"
}
// 获取点的详细信息
public func getInfo(): String {
let quadrant = match (getQuadrant()) {
case Quadrant.Origin => "原点"
case Quadrant.First => "第一象限"
case Quadrant.Second => "第二象限"
case Quadrant.Third => "第三象限"
case Quadrant.Fourth => "第四象限"
case Quadrant.XAxis => "X轴"
case Quadrant.YAxis => "Y轴"
}
return "${toString()}, 位于:${quadrant}"
}
}
main() {
let pts: Array<Point> = [ Point(1, 2), Point(-3, 4), Point(0, -6) ]
for (i in 0..pts.size) {
print("第${i+1}个点的坐标是")
println("${pts[i].getInfo()}")
}
}