第8篇:类和对象——面向对象编程

**作者:**中文编程倡导者—— 李金雨
联系方式: wbtm2718@qq.com
**目标读者:**编程入门(零基础)
核心理念: 使用华为仓颉原生中文编程,体验真正的国产编程语言


一、开篇引入

1.1 从"过程"到"对象"

前面的课程,我们学习的是"面向过程"编程——按照步骤一步一步执行。

现在,我们要学习更强大的"面向对象"编程——把现实世界的事物抽象成"对象"。

1.2 什么是对象?

生活例子:

你周围的一切都是"对象":

  • 👤 学生对象:有姓名、年龄、班级,能学习、能考试
  • 📱 手机对象:有品牌、颜色、价格,能打电话、能拍照
  • 🚗 汽车对象:有品牌、颜色、速度,能启动、能刹车

每个对象都有:

  • 属性(特征):姓名、年龄、颜色…
  • 方法(行为):学习、打电话、启动…

1.3 关于类定义的语法思考

在学习类之前,我们再聊聊仓颉的语法设计。

仓颉的类定义是:

class 学生 {
    var 姓名: String
    var 年龄: Int64
    
    init(姓名: String, 年龄: Int64) {
        this.姓名 = 姓名
        this.年龄 = 年龄
    }
}

这里又出现了类型后置的问题!var 姓名: String中,类型String放在了变量名后面。

如果仓颉能像C#那样:

// C#风格
class 学生 {
    public string 姓名;
    public int 年龄;
    
    public 学生(string 姓名, int 年龄) {
        this.姓名 = 姓名;
        this.年龄 = 年龄;
    }
}

这样读起来就是"字符串 姓名",而不是"姓名 字符串",更符合中国人的定语前置习惯!

不过,仓颉的class关键字表示"类",还是比较直观的。而且类名、属性名、方法名都可以用中文,这一点很好!

1.4 本课目标

今天我们要学习:

  1. 什么是类(模板)
  2. 什么是对象(实例)
  3. 如何定义类
  4. 如何创建对象
  5. 属性(特征)和方法(行为)
  6. 构造函数
  7. 做一个学生管理系统

二、概念讲解

2.1 类(Class)——对象的模板

什么是类?

是创建对象的"模板"或"蓝图"。

就像建筑图纸:

  • 图纸(类)定义了房子应该有什么(房间、门窗)
  • 根据图纸可以建造很多房子(对象)
定义类
class 学生 {
    // 属性(特征)
    var 姓名: String
    var 年龄: Int64
    var 班级: String
    
    // 构造函数
    init(姓名: String, 年龄: Int64, 班级: String) {
        this.姓名 = 姓名
        this.年龄 = 年龄
        this.班级 = 班级
    }
    
    // 方法(行为)
    func 自我介绍(): Unit {
        println("大家好,我叫${姓名},今年${年龄}岁,来自${班级}班。")
    }
    
    func 学习(): Unit {
        println("${姓名}正在认真学习...")
    }
    
    func 考试(成绩: Int64): Unit {
        println("${姓名}考了${成绩}分")
        if (成绩 >= 60) {
            println("及格了!")
        } else {
            println("不及格,要加油!")
        }
    }
}

再次吐槽类型后置

var 姓名: Stringfunc 自我介绍(): Unit,类型都放在了后面。

如果改进成类型前置:

// 设想中的改进
class 学生 {
    String 姓名
    Int64 年龄
    
    func 自我介绍(): Unit {    // 返回类型后置还可以接受
        // 代码
    }
}

希望华为能在未来版本中考虑!

2.2 对象(Object)——类的实例

什么是对象?

对象是根据类创建的具体事物。

就像根据图纸建造的房子:

  • 图纸(类):定义了房子的结构
  • 房子1(对象):张三的家
  • 房子2(对象):李四的家
创建对象
main() {
    // 创建学生对象
    let 张三 = 学生("张三", 15, "初三(1)")
    let 李四 = 学生("李四", 16, "初三(2)")
    let 王五 = 学生("王五", 15, "初三(1)")
    
    // 使用对象的方法
    张三.自我介绍()
    张三.学习()
    张三.考试(85)
    
    println("")
    
    李四.自我介绍()
    李四.考试(92)
}

2.3 访问属性

main() {
    let 张三 = 学生("张三", 15, "初三(1)")
    
    // 访问属性
    println("姓名:${张三.姓名}")
    println("年龄:${张三.年龄}")
    
    // 修改属性
    张三.年龄 = 16
    println("修改后的年龄:${张三.年龄}")
}

2.4 封装——保护数据

什么是封装?

封装就是把数据保护起来,只能通过特定方法访问。

就像ATM机:

  • 你的存款(数据)被保护在机器里
  • 只能通过插卡、输密码(方法)来访问
代码示例
class 银行账户 {
    // 私有属性(外部不能直接访问)
    private var 余额: Float64
    private var 密码: String
    
    // 公有属性
    public var 账号: String
    public var 户名: String
    
    init(账号: String, 户名: String, 初始余额: Float64, 密码: String) {
        this.账号 = 账号
        this.户名 = 户名
        this.余额 = 初始余额
        this.密码 = 密码
    }
    
    // 存款(公有方法)
    public func 存款(金额: Float64): Unit {
        if (金额 > 0) {
            余额 = 余额 + 金额
            println("存款成功,当前余额:${余额}")
        } else {
            println("存款金额必须大于0")
        }
    }
    
    // 取款(公有方法)
    public func 取款(金额: Float64, 输入密码: String): Unit {
        if (输入密码 != 密码) {
            println("密码错误!")
            return
        }
        if (金额 > 余额) {
            println("余额不足!")
            return
        }
        余额 = 余额 - 金额
        println("取款成功,当前余额:${余额}")
    }
    
    // 查询余额(公有方法)
    public func 查询余额(输入密码: String): Float64 {
        if (输入密码 != 密码) {
            println("密码错误!")
            return 0.0
        }
        return 余额
    }
}

main() {
    let 我的账户 = 银行账户("622202123456789", "张三", 1000.0, "123456")
    
    println("户名:${我的账户.户名}")
    println("账号:${我的账户.账号}")
    
    // 存款
    我的账户.存款(500.0)
    
    // 取款
    我的账户.取款(200.0, "123456")
    
    // 查询余额
    let 余额 = 我的账户.查询余额("123456")
    println("当前余额:${余额}")
}

三、动手实践

3.1 基础练习:学生类

// 学生类

class 学生 {
    // 属性
    var 姓名: String
    var 年龄: Int64
    var 班级: String
    var 成绩: Int64
    
    // 构造函数
    init(姓名: String, 年龄: Int64, 班级: String, 成绩: Int64) {
        this.姓名 = 姓名
        this.年龄 = 年龄
        this.班级 = 班级
        this.成绩 = 成绩
    }
    
    // 方法
    func 自我介绍(): Unit {
        println("大家好,我叫${姓名},今年${年龄}岁,来自${班级}班。")
    }
    
    func 学习(): Unit {
        println("${姓名}正在认真学习...")
    }
    
    func 考试(): Unit {
        println("${姓名}参加了考试,考了${成绩}分")
        if (成绩 >= 90) {
            println("评价:优秀")
        } else if (成绩 >= 80) {
            println("评价:良好")
        } else if (成绩 >= 60) {
            println("评价:及格")
        } else {
            println("评价:不及格")
        }
    }
    
    func 升级(): Unit {
        年龄 = 年龄 + 1
        println("${姓名}升级了,现在${年龄}岁")
    }
}

main() {
    println("=== 学生管理系统 ===")
    println("")
    
    // 创建学生对象
    let 张三 = 学生("张三", 15, "初三(1)", 85)
    let 李四 = 学生("李四", 16, "初三(2)", 92)
    let 王五 = 学生("王五", 15, "初三(1)", 78)
    
    // 学生列表
    let 学生列表 = [张三, 李四, 王五]
    
    // 显示所有学生信息
    println("【所有学生】")
    for (学生 in 学生列表) {
        学生.自我介绍()
    }
    
    println("")
    
    // 让所有学生学习
    println("【学习时间】")
    for (学生 in 学生列表) {
        学生.学习()
    }
    
    println("")
    
    // 让所有学生考试
    println("【考试时间】")
    for (学生 in 学生列表) {
        学生.考试()
        println("")
    }
    
    // 升级
    println("【升级】")
    for (学生 in 学生列表) {
        学生.升级()
    }
}

3.2 进阶练习:图书类

// 图书类

class 图书 {
    // 属性
    var 书名: String
    var 作者: String
    var 出版社: String
    var 价格: Float64
    var 是否借出: Bool
    
    // 构造函数
    init(书名: String, 作者: String, 出版社: String, 价格: Float64) {
        this.书名 = 书名
        this.作者 = 作者
        this.出版社 = 出版社
        this.价格 = 价格
        this.是否借出 = false
    }
    
    // 方法
    func 显示信息(): Unit {
        println("《${书名}》")
        println("作者:${作者}")
        println("出版社:${出版社}")
        println("价格:${价格}元")
        println("状态:${是否借出 ? "已借出" : "可借阅"}")
    }
    
    func 借阅(): Unit {
        if (是否借出) {
            println("抱歉,《${书名}》已被借出")
        } else {
            是否借出 = true
            println("《${书名}》借阅成功")
        }
    }
    
    func 归还(): Unit {
        if (!是否借出) {
            println("《${书名}》没有被借出")
        } else {
            是否借出 = false
            println("《${书名}》归还成功")
        }
    }
}

main() {
    println("=== 图书馆管理系统 ===")
    println("")
    
    // 创建图书
    let 图书1 = 图书("西游记", "吴承恩", "人民文学出版社", 45.0)
    let 图书2 = 图书("红楼梦", "曹雪芹", "人民文学出版社", 50.0)
    let 图书3 = 图书("三国演义", "罗贯中", "人民文学出版社", 48.0)
    
    let 图书列表 = [图书1, 图书2, 图书3]
    
    // 显示所有图书
    println("【图书馆藏书】")
    for (图书 in 图书列表) {
        图书.显示信息()
        println("")
    }
    
    // 借阅图书
    println("【借阅操作】")
    图书1.借阅()
    图书1.借阅()    // 再次借阅,应该失败
    
    println("")
    
    // 归还图书
    println("【归还操作】")
    图书1.归还()
}

3.3 挑战练习:游戏角色类

// 游戏角色类

class 角色 {
    // 属性
    var 名字: String
    var 职业: String
    var 等级: Int64
    var 生命值: Int64
    var 魔法值: Int64
    var 攻击力: Int64
    var 防御力: Int64
    
    // 构造函数
    init(名字: String, 职业: String) {
        this.名字 = 名字
        this.职业 = 职业
        this.等级 = 1
        this.生命值 = 100
        this.魔法值 = 50
        this.攻击力 = 10
        this.防御力 = 5
    }
    
    // 方法
    func 显示状态(): Unit {
        println("【${名字}】")
        println("职业:${职业}")
        println("等级:${等级}")
        println("生命值:${生命值}")
        println("魔法值:${魔法值}")
        println("攻击力:${攻击力}")
        println("防御力:${防御力}")
    }
    
    func 升级(): Unit {
        等级 = 等级 + 1
        生命值 = 生命值 + 20
        魔法值 = 魔法值 + 10
        攻击力 = 攻击力 + 5
        防御力 = 防御力 + 3
        println("${名字}升级了!当前等级:${等级}")
    }
    
    func 攻击(目标: 角色): Unit {
        let 伤害 = 攻击力 - 目标.防御力
        if (伤害 > 0) {
            目标.生命值 = 目标.生命值 - 伤害
            println("${名字}攻击了${目标.名字},造成${伤害}点伤害")
        } else {
            println("${名字}攻击了${目标.名字},但未造成伤害")
        }
    }
    
    func 是否存活(): Bool {
        return 生命值 > 0
    }
}

main() {
    println("=== 角色对战 ===")
    println("")
    
    // 创建角色
    let 战士 = 角色("亚瑟", "战士")
    let 法师 = 角色("梅林", "法师")
    
    // 显示初始状态
    println("【初始状态】")
    战士.显示状态()
    println("")
    法师.显示状态()
    
    println("")
    
    // 升级
    println("【升级】")
    战士.升级()
    战士.升级()
    
    println("")
    
    // 对战
    println("【对战开始】")
    while (战士.是否存活() && 法师.是否存活()) {
        战士.攻击(法师)
        if (法师.是否存活()) {
            法师.攻击(战士)
        }
        println("")
    }
    
    // 显示结果
    println("【对战结束】")
    if (战士.是否存活()) {
        println("${战士.名字}获胜!")
    } else {
        println("${法师.名字}获胜!")
    }
}

四、知识总结

4.1 核心概念回顾

  1. :创建对象的模板
  2. 对象:类的实例
  3. 属性:对象的特征
  4. 方法:对象的行为
  5. 构造函数:创建对象时初始化
  6. 封装:保护数据

4.2 关于语法设计的总结

仓颉的类定义语法:

class 学生 {
    var 姓名: String
    var 年龄: Int64
    
    init(姓名: String, 年龄: Int64) {
        this.姓名 = 姓名
        this.年龄 = 年龄
    }
}

优点:

  • class关键字直观
  • 类名、属性名、方法名可以用中文
  • 支持封装

可以改进的地方:

  • 属性类型后置
  • 方法返回类型后置

如果改进成类型前置:

// 设想中的改进
class 学生 {
    String 姓名
    Int64 年龄
    
    学生(String 姓名, Int64 年龄) {
        this.姓名 = 姓名
        this.年龄 = 年龄
    }
}

希望华为能在未来版本中考虑!

4.3 关键代码速查

// 定义类
class 类名 {
    // 属性
    var 属性名: 类型
    
    // 构造函数
    init(参数: 类型) {
        this.属性名 = 参数
    }
    
    // 方法
    func 方法名(): 返回类型 {
        return 结果
    }
}

// 创建对象
let 对象 = 类名(参数)

// 访问属性
对象.属性名

// 调用方法
对象.方法名()

4.4 常见错误提醒

错误现象 原因 解决方法
属性未初始化 构造函数中没有赋值 在init中初始化
无法访问私有属性 属性是private 使用公有方法访问
方法调用错误 方法名错误或对象为空 检查方法名和对象

五、课后作业

5.1 巩固练习(必做)

练习1:设计汽车类

属性:品牌、颜色、速度、油量
方法:启动、加速、刹车、加油

练习2:设计动物类

属性:名字、种类、年龄
方法:吃、睡、叫

练习3:设计购物车类

属性:商品列表、总价
方法:添加商品、删除商品、计算总价

5.2 创意编程(选做)

创意1:设计游戏角色系统

战士、法师、弓箭手等不同职业。

创意2:设计银行账户系统

支持存款、取款、转账、查询余额。

创意3:设计学校管理系统

学生、老师、课程、成绩管理。

5.3 下篇预习

下一篇,我们将学习继承和多态,这是面向对象编程的高级特性。


恭喜你完成了第8篇的学习! 🎉

现在你已经掌握了面向对象编程的基础,可以创建类和对象了!

下节课,我们将学习继承和多态,这是更强大的面向对象特性!

Logo

一站式 AI 云服务平台

更多推荐