当前位置: 首页 > news >正文

TypeScript 继承与多态

本文献给:

已掌握 TypeScript 类基础(字段、构造函数、方法、访问修饰符、参数属性)的开发者。本文将带你学习类的继承(extendssuper)、方法重写与override关键字,以及多态在 TypeScript 中的实现方式。


你将学到:

  1. extends关键字实现类继承
  2. super调用父类构造函数与方法
  3. 方法重写与override关键字(TS 4.3+)
  4. 多态的概念与示例
  5. 继承与访问修饰符的交互规则


目录

  • 一、extends 继承
  • 二、super 关键字
    • 2.1 调用父类构造函数
    • 2.2 调用父类方法
  • 三、方法重写
    • 3.1 override 关键字(TypeScript 4.3+)
  • 四、多态
    • 4.1 多态的优势
  • 五、继承与访问修饰符的交互
    • 5.1 public
    • 5.2 protected
    • 5.3 private
    • 5.4 子类可以放宽访问权限吗?
  • 六、常见错误与注意事项
    • 6.1 忘记调用 super
    • 6.2 在 super 之前访问 this
    • 6.3 重写方法时返回类型不兼容
    • 6.4 子类属性与父类属性同名
    • 6.5 override 关键字版本要求
  • 七、综合示例
  • 八、小结

一、extends 继承

使用extends关键字让一个类继承另一个类的所有属性和方法。

classAnimal{name:string;constructor(name:string){this.name=name;}move(distance:number=0){console.log(`${this.name}moved${distance}m`);}}classDogextendsAnimal{bark(){console.log(`${this.name}barks`);}}constdog=newDog("Buddy");dog.bark();// "Buddy barks"dog.move(10);// "Buddy moved 10m"

子类拥有父类的所有publicprotected成员,private成员不可继承。


二、super 关键字

2.1 调用父类构造函数

如果在子类中定义了构造函数,则必须使用super()调用父类构造函数,且必须在访问this之前调用。

classAnimal{name:string;constructor(name:string){this.name=name;}}classDogextendsAnimal{breed:string;constructor(name:string,breed:string){super(name);// 必须先调用 superthis.breed=breed;}}

2.2 调用父类方法

在子类方法中可以使用super.methodName()调用父类的原始方法。

classAnimal{speak(){console.log("Animal makes sound");}}classDogextendsAnimal{speak(){super.speak();// 调用父类方法console.log("Dog barks");}}constd=newDog();d.speak();// "Animal makes sound"// "Dog barks"

三、方法重写

子类可以重写父类的方法,提供自己的实现。

classVehicle{start():void{console.log("Vehicle starting...");}}classCarextendsVehicle{start():void{console.log("Car engine roaring...");}}constmyCar=newCar();myCar.start();// "Car engine roaring..."

3.1 override 关键字(TypeScript 4.3+)

TypeScript 4.3 引入了override关键字,用于显式标记方法重写父类方法。这可以避免因父类方法更名或删除而导致的意外错误。

classParent{greet(){console.log("Hello");}}classChildextendsParent{overridegreet(){console.log("Hi");}}

如果父类中没有greet方法,override会报错:

classChildextendsParent{overridesayHi(){// ❌ 父类中没有 sayHi 方法console.log("Hi");}}

override关键字让代码意图更清晰,推荐在重写方法时使用。


四、多态

多态是指同一个方法在不同子类中表现出不同的行为。父类类型的变量可以指向子类对象,调用重写的方法时,实际执行的是子类的实现。

classShape{area():number{return0;}}classCircleextendsShape{radius:number;constructor(radius:number){super();this.radius=radius;}overridearea():number{returnMath.PI*this.radius**2;}}classRectangleextendsShape{width:number;height:number;constructor(width:number,height:number){super();this.width=width;this.height=height;}overridearea():number{returnthis.width*this.height;}}functionprintArea(shape:Shape){console.log(`Area:${shape.area()}`);}constshapes:Shape[]=[newCircle(5),newRectangle(4,6)];shapes.forEach(printArea);// Area: 78.53981633974483// Area: 24

4.1 多态的优势

  • 代码复用:使用父类类型的参数可以接受任意子类实例。
  • 扩展性:新增子类无需修改已有函数。

五、继承与访问修饰符的交互

5.1 public

public成员在子类中保持public,可被任意访问。

5.2 protected

protected成员在子类内部可访问,但通过子类实例在外部不可访问。

classParent{protectedvalue=42;}classChildextendsParent{show(){console.log(this.value);// OK}}constc=newChild();console.log(c.value);// ❌ 属性受保护

5.3 private

private成员不被继承,子类中无法访问。

classParent{privatesecret="hidden";}classChildextendsParent{try(){// console.log(this.secret); // ❌ 属性私有}}

5.4 子类可以放宽访问权限吗?

子类重写方法时,不能降低父类方法的访问权限(即不能将public改为protectedprivate),但可以提升(将protected改为public是允许的)。

classParent{protecteddoSomething(){}}classChildextendsParent{publicdoSomething(){}// OK,放宽权限}

六、常见错误与注意事项

6.1 忘记调用 super

在子类构造函数中,如果省略super(),TypeScript 会报错。

classChildextendsParent{constructor(){// 缺少 super() ❌}}

6.2 在 super 之前访问 this

classChildextendsParent{constructor(){console.log(this);// ❌ 在 super 之前不能使用 thissuper();}}

6.3 重写方法时返回类型不兼容

重写方法的返回类型必须是父类方法返回类型的子类型。

classParent{get():object{return{};}}classChildextendsParent{overrideget():string{// ❌ string 不是 object 的子类型return"hello";}}

6.4 子类属性与父类属性同名

如果子类声明了与父类同名的属性,会覆盖父类的属性(但建议避免这样做,容易造成混淆)。

classParent{name="Parent";}classChildextendsParent{name="Child";// 覆盖}constc=newChild();console.log(c.name);// "Child"

6.5 override 关键字版本要求

override需要 TypeScript 4.3+ 且noImplicitOverride标志启用(或严格模式)。如果没有启用,override只是普通标识符,但建议在tsconfig.json中开启"noImplicitOverride": true


七、综合示例

// 抽象一个媒体播放器基类classMediaPlayer{protectedcurrentVolume:number=50;constructor(protectedname:string){}play():void{console.log(`${this.name}starts playing`);}pause():void{console.log(`${this.name}pauses`);}setVolume(volume:number):void{this.currentVolume=volume;console.log(`Volume set to${volume}`);}}// 音频播放器子类classAudioPlayerextendsMediaPlayer{privateequalizer:boolean=false;constructor(name:string,privatebitrate:number){super(name);}overrideplay():void{console.log(`AudioPlayer${this.name}plays at${this.bitrate}kbps`);}enableEqualizer():void{this.equalizer=true;console.log("Equalizer enabled");}// 重写并调用父类方法overridesetVolume(volume:number):void{super.setVolume(volume);console.log(`Audio volume adjusted to${volume}`);}}// 视频播放器子类classVideoPlayerextendsMediaPlayer{privatesubtitlesEnabled:boolean=false;overrideplay():void{console.log(`VideoPlayer${this.name}plays with subtitles:${this.subtitlesEnabled}`);}toggleSubtitles():void{this.subtitlesEnabled=!this.subtitlesEnabled;console.log(`Subtitles${this.subtitlesEnabled?"enabled":"disabled"}`);}// 不重写 setVolume,沿用父类行为}// 多态使用functioncontrolMedia(players:MediaPlayer[]){players.forEach(player=>{player.play();player.setVolume(70);player.pause();});}constaudio=newAudioPlayer("Spotify",320);constvideo=newVideoPlayer("Netflix");audio.enableEqualizer();video.toggleSubtitles();controlMedia([audio,video]);// 检查类型if(audioinstanceofAudioPlayer){audio.enableEqualizer();// 类型守卫后可用特有方法}

八、小结

概念语法/示例说明
继承class Child extends Parent子类获得父类非私有成员
super 调用构造函数super(args)子类构造函数中必须调用
super 调用方法super.method()调用父类原始方法
方法重写子类中定义同名方法覆盖父类实现
override 关键字override method() {}显式标记重写,增强安全性
多态父类类型变量指向子类实例调用重写方法执行子类版本
权限交互protected可被继承,private不可子类可放宽但不能缩小访问权限



觉得文章有帮助?别忘了:

👍 点赞 👍– 给我一点鼓励
⭐ 收藏 ⭐– 方便以后查看
🔔 关注 🔔– 获取更新通知



标签:#TypeScript#继承#多态#面向对象#学习笔记#前端开发

http://www.cnnetsun.cn/news/2565275.html

相关文章:

  • 百川AI医生+DeepSeek代码智能体:AI赛道双线突破
  • 2026年盛时表行门店深度解析:线下购表场景信任缺失与售后保障瓶颈
  • 暗黑破坏神2存档修改器:Diablo Edit2让你的游戏体验随心所欲
  • 2026年一键生成论文工具对比实测:5款神器从选题到格式全流程护航
  • HDI 高密度互连板阶数的深度理解
  • 零基础转行网络安全!通俗拆解行业岗位、能力要求与发展路径
  • GEO生成引擎优化:当AI成为信息分发的主角,品牌如何抢占对话窗口?
  • 黑客必刷的 23 个网安攻防靶场,零基础到红队全覆盖
  • 别再乱点屏幕了!用Monkey黑白名单精准测试你的Android App(附完整配置文件)
  • 如何免费解锁WeMod专业版功能:Wand-Enhancer完整指南
  • 论文的格式是什么?
  • 为什么MPC Video Renderer能实现零拷贝视频渲染?深度解析DirectShow渲染器的技术突破
  • 别再傻傻复制粘贴了!用mklink硬链接/Junction,给Windows文件夹做个‘分身术’
  • 毕业设计:基于mvc的高校办公室行政事务管理系统设计与实现(源码)
  • 为什么鸿蒙 App 最终都会走向状态驱动?
  • 中小型企业做GEO优化性价比高吗
  • PDF4QT:免费开源的PDF全能工具箱,轻松处理各类文档难题
  • 别再只会用Linux虚拟机了!手把手教你给Windows Server 2019/2022配置OpenSSH服务端,实现Xshell/Xftp直连
  • Keil µVision链接器错误204解决方案
  • OAuth2调试利器:oauth2-mock-server实战指南
  • 3分钟学会NCM解密:让网易云音乐文件在任何设备自由播放!
  • 机器学习原子模拟中的不确定性量化:贝叶斯与集成方法实践指南
  • Web渗透中框架组件识别的三维可信度模型与实战穿透
  • GDRE Tools:Godot二进制调试与资产复用技术指南
  • Kotlin 委托详解
  • 智慧城配管理系统,解锁物流运营全新竞争力
  • 双层 HITL 架构:为什么你的 AI 客服需要前置规则 + 后置兜底?
  • Spring Security OAuth2 /oauth/token 401原因与Content-Type规范
  • ssm果蔬经营平台系统(10105)
  • RAG 检索增强生成实战:从 Demo 到生产环境的五个关键优化