第9篇 继承和多态——面向对象的扩展

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


一、什么是继承?

继承是面向对象编程中非常重要的概念。想象一下,你的父母有一些特征(比如眼睛颜色、血型)遗传给了你,这就是现实生活中的"继承"。

在编程中,继承让一个类可以"继承"另一个类的属性和方法,避免重复写代码。

二、生活中的继承例子

例子1:动物分类

  • 动物(基类):都有名字、都会呼吸
    • (子类):继承自动物,还会汪汪叫
    • (子类):继承自动物,还会喵喵叫
    • (子类):继承自动物,还会飞

例子2:交通工具

  • 交通工具(基类):都有品牌、都能移动
    • 汽车(子类):有4个轮子,烧汽油
    • 自行车(子类):有2个轮子,靠人力
    • 飞机(子类):有翅膀,烧航空煤油

三、仓颉语言中的继承

在仓颉中,使用 : 表示继承关系。

基础语法

// 基类:动物
open class 动物 {
    var 名字: String
    var 年龄: Int64
    
    init(名字: String, 年龄: Int64) {
        this.名字 = 名字
        this.年龄 = 年龄
    }
    
    open func 发出声音(): Unit {
        println("动物发出声音")
    }
    
    func 呼吸(): Unit {
        println("${名字}在呼吸")
    }
}

// 子类:狗,继承自动物
class 狗 : 动物 {
    var 品种: String
    
    init(名字: String, 年龄: Int64, 品种: String) {
        this.品种 = 品种
        super.init(名字, 年龄)  // 调用父类的构造方法
    }
    
    // 重写父类的方法
    override func 发出声音(): Unit {
        println("${名字}:汪汪汪!")
    }
    
    func 摇尾巴(): Unit {
        println("${名字}在开心地摇尾巴")
    }
}

// 子类:猫,继承自动物
class 猫 : 动物 {
    var 毛色: String
    
    init(名字: String, 年龄: Int64, 毛色: String) {
        this.毛色 = 毛色
        super.init(名字, 年龄)
    }
    
    override func 发出声音(): Unit {
        println("${名字}:喵喵喵~")
    }
    
    func 抓老鼠(): Unit {
        println("${名字}在抓老鼠")
    }
}

main() {
    var 我的狗 = 狗("旺财", 3, "金毛")
    var 我的猫 = 猫("咪咪", 2, "橘色")
    
    我的狗.呼吸()        // 继承自父类的方法
    我的狗.发出声音()     // 子类重写的方法
    我的狗.摇尾巴()       // 子类自己的方法
    
    我的猫.呼吸()
    我的猫.发出声音()
    我的猫.抓老鼠()
}

运行结果

旺财在呼吸
旺财:汪汪汪!
旺财在开心地摇尾巴
咪咪在呼吸
咪咪:喵喵喵~
咪咪在抓老鼠

四、语法设计讨论:继承中的类型声明

同学们,在学习继承的时候,我们再次遇到了仓颉的类型后置语法问题。

看看上面的代码:

open class 动物 {
    var 名字: String      // 类型后置
    var 年龄: Int64       // 类型后置
    
    open func 发出声音(): Unit {  // 返回值类型后置
        // ...
    }
}

class 狗 : 动物 {        // 这里继承关系倒是挺清晰的
    var 品种: String      // 又是类型后置
}

按照中国人的语言习惯:

  • 我们习惯说"动物类的基类"、“狗类继承自动物类”
  • 我们习惯说"字符串类型的名字"、“整数类型的年龄”

但仓颉的写法:

  • var 名字: String → 读作"名字,字符串类型的"(定语后置)
  • class 狗 : 动物 → 读作"狗类继承自动物类"(这个倒是符合习惯)

如果仓颉能改进成C#风格:

// 假设的改进语法
open class 动物 {
    String 名字      // "字符串类型的名字"——定语前置,符合中文习惯!
    Int64 年龄       // "整数类型的年龄"
    
    open Unit 发出声音() {  // "无返回值类型的发出声音方法"
        // ...
    }
}

这样读起来就像在说:"定义一个动物类,它有一个字符串类型的名字属性,一个整数类型的年龄属性…"多么自然!

华为在设计仓颉语言时,继承了Rust的类型后置语法,这就像是继承了古汉语的"定语后置"习惯。但现代中国人日常说话都是"定语前置"的,我们希望未来的中文编程语言能真正做到"说人话"!

五、什么是多态?

多态(Polymorphism)是面向对象的另一个重要特性。通俗地说,就是"同一个方法,不同的表现"。

生活例子

  • "叫"这个动作

    • 狗叫是"汪汪汪"
    • 猫叫是"喵喵喵"
    • 鸟叫是"叽叽喳喳"
  • "移动"这个动作

    • 汽车移动是"在公路上跑"
    • 飞机移动是"在天上飞"
    • 轮船移动是"在水上航行"

代码示例

// 使用前面的动物类定义

func 让动物叫(某动物: 动物): Unit {
    某动物.发出声音()  // 同样是发出声音,不同的动物有不同的表现
}

main() {
    var 动物们: Array<动物> = [
        狗("旺财", 3, "金毛"),
        猫("咪咪", 2, "橘色"),
        狗("大黄", 5, "中华田园犬")
    ]
    
    for (某动物 in 动物们) {
        让动物叫(某动物)  // 多态:同一个方法调用,不同对象有不同行为
    }
}

运行结果

旺财:汪汪汪!
咪咪:喵喵喵~
大黄:汪汪汪!

六、super关键字

super 用于调用父类的方法或属性。

class 学生 : 人 {
    var 学号: String
    var 成绩: Float64
    
    init(姓名: String, 年龄: Int64, 学号: String, 成绩: Float64) {
        this.学号 = 学号
        this.成绩 = 成绩
        super.init(姓名, 年龄)  // 调用父类的构造方法
    }
    
    override func 自我介绍(): Unit {
        super.自我介绍()  // 先调用父类的自我介绍
        println("我的学号是${学号},成绩是${成绩}分")
    }
}

七、练习时间

练习1:图形继承

创建一个图形类体系:

  • 基类图形:有颜色属性,有计算面积的方法
  • 子类矩形:有长和宽,重写计算面积方法
  • 子类圆形:有半径,重写计算面积方法
  • 子类三角形:有底和高,重写计算面积方法

练习2:员工管理系统

  • 基类员工:有姓名、工号、基本工资
  • 子类普通员工:按固定工资计算
  • 子类销售员:有销售额,工资=基本工资+提成
  • 子类经理:有部门,工资=基本工资+奖金

练习3:游戏角色

  • 基类角色:有名字、生命值、攻击力
  • 子类战士:有高生命值,普通攻击
  • 子类法师:有魔法值,可以释放魔法
  • 子类弓箭手:可以远程攻击

八、本课小结

今天我们学习了:

  1. 继承:子类继承父类的属性和方法,避免代码重复
  2. 多态:同一个方法调用,不同对象有不同表现
  3. 方法重写:子类可以重写父类的方法
  4. super关键字:调用父类的方法

类型语法思考:在继承体系中,我们频繁地声明类、属性、方法,每一次都要面对var 属性名: 类型这种定语后置的语法。希望未来的中文编程语言能让类型声明更符合中国人的说话习惯!

九、课后作业

  1. 设计一个"图书馆管理系统"的类结构:

    • 基类图书:书名、作者、ISBN、价格
    • 子类小说:有故事简介
    • 子类教科书:有适用年级、学科
    • 子类杂志:有期号、出版社
  2. 实现一个计算总价格的多态方法,不同类型的图书可能有不同的折扣。

  3. 思考:在你的生活中,还有哪些可以用继承和多态来描述的关系?


下篇预告:第10篇《异常处理——程序的容错机制》,学习如何让程序在遇到错误时优雅地处理,而不是直接崩溃!

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐