第9篇 继承和多态——面向对象的扩展 仓颉原生中文编程
本文介绍了面向对象编程中的继承和多态概念。通过动物分类、交通工具等生活化例子,阐述了继承如何让子类获得父类特性并扩展新功能。文章详细展示了仓颉语言中的继承语法(使用":"符号),包括方法重写、super关键字使用等核心知识点,并讨论了类型声明语法与中文习惯的差异。多态部分通过"动物叫声"等实例说明同一方法在不同子类中的不同表现。最后提供了图形计算、员工管理、
第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:游戏角色
- 基类
角色:有名字、生命值、攻击力 - 子类
战士:有高生命值,普通攻击 - 子类
法师:有魔法值,可以释放魔法 - 子类
弓箭手:可以远程攻击
八、本课小结
今天我们学习了:
- 继承:子类继承父类的属性和方法,避免代码重复
- 多态:同一个方法调用,不同对象有不同表现
- 方法重写:子类可以重写父类的方法
- super关键字:调用父类的方法
类型语法思考:在继承体系中,我们频繁地声明类、属性、方法,每一次都要面对var 属性名: 类型这种定语后置的语法。希望未来的中文编程语言能让类型声明更符合中国人的说话习惯!
九、课后作业
-
设计一个"图书馆管理系统"的类结构:
- 基类
图书:书名、作者、ISBN、价格 - 子类
小说:有故事简介 - 子类
教科书:有适用年级、学科 - 子类
杂志:有期号、出版社
- 基类
-
实现一个
计算总价格的多态方法,不同类型的图书可能有不同的折扣。 -
思考:在你的生活中,还有哪些可以用继承和多态来描述的关系?
下篇预告:第10篇《异常处理——程序的容错机制》,学习如何让程序在遇到错误时优雅地处理,而不是直接崩溃!
更多推荐

所有评论(0)