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

TypeScript 从零基础到精通(四):面向对象编程(类与继承)

摘要:面向对象编程(OOP)是现代软件开发的重要范式。TypeScript 在 JavaScript 原型链的基础上,提供了完整的类(Class)语法和增强特性:访问修饰符(public/private/protected)、抽象类、静态成员、类与接口的配合等。本文从零讲解 TypeScript 中的类,并结合封装、继承、多态三大特性,帮助你写出结构清晰、可复用的代码。


一、前言

前三篇文章中,我们学习了 TypeScript 的基础类型、函数、对象和接口。现在我们可以为普通的 JavaScript 代码加上类型注解,用接口定义对象结构。

但是,当项目规模增长,我们需要更强大的组织代码的方式——面向对象编程(OOP)。OOP 将数据和对数据的操作封装在一起(类),通过继承实现代码复用,通过多态应对变化。TypeScript 让 JavaScript 的类更加强大和严谨。


二、JavaScript 类的演变

ES6(ES2015)为 JavaScript 引入了class语法糖,但它本质上还是基于原型链。TypeScript 在此基础上增加了类型系统和面向对象设计的增强特性。

ES6 类示例

class Animal { constructor(name) { this.name = name; } speak() { console.log(`${this.name} makes a sound.`); } }

问题:ES6 类没有真正的私有成员(只能通过约定_nameSymbol模拟),也没有类型约束。

TypeScript 填补了这些空白。


三、TypeScript 中的类基础

3.1 类的基本定义

使用class关键字定义类,属性需要提前声明类型(不像 JavaScript 动态添加)。

class Person { name: string; // 声明属性(实例属性) age: number; ​ constructor(name: string, age: number) { this.name = name; this.age = age; } ​ greet(): void { console.log(`Hello, I'm ${this.name}, ${this.age} years old.`); } } ​ const p = new Person("Alice", 30); p.greet(); // Hello, I'm Alice, 30 years old.

注意:TypeScript 要求在构造函数中明确初始化所有声明了的属性,否则会报错(除非开启strictPropertyInitialization或使用非空断言!)。

3.2 构造函数(constructor)

构造函数在new时执行,用于初始化实例。参数和返回值的类型注解与普通函数一样。

class Student { name: string; grade: number; ​ constructor(name: string, grade: number) { this.name = name; this.grade = grade; } }

如果参数带有默认值或修饰符(见下文),可以使用更简洁的写法。

3.3 实例属性与方法

实例属性就是this.xxx,实例方法直接定义在类内部。

class Counter { count: number = 0; // 可以直接赋初始值 ​ increment(): void { this.count++; } ​ getValue(): number { return this.count; } }

四、访问修饰符:public、private、protected

TypeScript 提供了三个修饰符来控制类成员的可见性。

修饰符含义
public默认值,任何地方都可访问
private只在当前类内部可访问,子类和实例不能访问
protected在当前类和子类内部可访问,实例不能访问

4.1 基本用法

class Animal { public name: string; // 公有(默认) private age: number; // 私有 protected species: string; // 受保护 ​ constructor(name: string, age: number, species: string) { this.name = name; this.age = age; this.species = species; } ​ private getAge(): number { // 私有方法 return this.age; } ​ public showInfo(): void { console.log(`${this.name}, age=${this.age}, species=${this.species}`); console.log(this.getAge()); // 内部可以调用私有方法 } } ​ const dog = new Animal("旺财", 3, "Canine"); console.log(dog.name); // ✅ 公有,可访问 // console.log(dog.age); // ❌ 私有,报错 // console.log(dog.species); // ❌ 受保护,实例不能访问 // dog.getAge(); // ❌ 私有方法

子类中的访问

class Dog extends Animal { bark(): void { console.log(`${this.name} bark!`); // ✅ 公有可以 // console.log(this.age); // ❌ 私有,子类也不能访问 console.log(this.species); // ✅ 受保护,子类可访问 } }

4.2 参数属性(Parameter Properties)—— 简化写法

TypeScript 提供了一种语法糖:在构造函数参数前直接加上修饰符,TS 会自动声明同名的实例属性并赋值。

class User { // 等价于先声明 public name: string; 然后在构造函数中 this.name = name constructor(public name: string, private age: number) {} ​ info(): string { return `${this.name}, ${this.age}`; } } ​ const u = new User("张三", 25); console.log(u.name); // ✅ 公有 // console.log(u.age); // ❌ 私有

这是非常实用的写法,可以减少重复代码。


五、继承(Inheritance)

继承是面向对象的核心之一,允许子类复用父类的属性和方法,并添加自己的特性。

5.1 extends 关键字

使用extends实现继承。

class Vehicle { constructor(public brand: string, public speed: number) {} ​ move(): void { console.log(`${this.brand} is moving at ${this.speed} km/h.`); } } ​ class Car extends Vehicle { doors: number; constructor(brand: string, speed: number, doors: number) { super(brand, speed); // 必须先调用 super() this.doors = doors; } ​ honk(): void { console.log(`${this.brand} horn: Beep beep!`); } } ​ const myCar = new Car("Toyota", 120, 4); myCar.move(); // 继承自父类 myCar.honk(); // 自己的方法

关键点

  • 子类构造函数中必须调用super(...)执行父类构造函数。

  • super必须在访问this之前调用。

5.2 方法重写(Override)

子类可以重写父类的方法,覆盖其行为。同时可以在重写的方法中使用super.method()调用父类版本。

class Animal { speak(): void { console.log("Animal makes a sound."); } } ​ class Cat extends Animal { speak(): void { console.log("Meow!"); } } ​ class Dog extends Animal { speak(): void { super.speak(); // 先调用父类方法 console.log("Woof!"); } } ​ new Cat().speak(); // Meow! new Dog().speak(); // Animal makes a sound. Woof!

TypeScript 建议在重写的方法上使用override关键字(TS 4.3+),便于明确意图和防止拼写错误。

class Bird extends Animal { override speak(): void { // 显式标记 override console.log("Chirp chirp"); } }

如果没有override但方法名写错(本意重写却写成了新方法),TS 会给出提示。


六、抽象类(Abstract Class)

抽象类是不能被实例化的类,用作其他类的基类。它可以包含抽象方法(没有实现,必须在子类中实现)和具体实现。

6.1 抽象方法与抽象类

使用abstract关键字。

abstract class Shape { abstract getArea(): number; // 抽象方法,没有方法体 ​ getType(): string { // 普通方法可以有实现 return "Shape"; } } ​ // const s = new Shape(); // ❌ 不能实例化抽象类 ​ class Circle extends Shape { constructor(public radius: number) { super(); } ​ getArea(): number { // 必须实现抽象方法 return Math.PI * this.radius ** 2; } } ​ const c = new Circle(5); console.log(c.getArea()); // 78.5398...

6.2 抽象类 vs 接口

抽象类接口
是否可实例化不适用(仅类型)
是否可以包含实现可以(普通方法、属性)不可以(纯声明,TS 中可放属性但无实现)
继承/实现子类extends单个抽象类类可以实现多个接口
用途提供公共基础实现,强制子类实现某些行为定义契约,完全抽离实现

实践建议:当多个类有共同的实现逻辑时用抽象类;仅定义行为规范时用接口。


七、静态成员(Static)

静态成员属于类本身,而不是实例。通过类名直接访问。

class MathUtils { static PI: number = 3.14159; ​ static circleArea(radius: number): number { return this.PI * radius * radius; // 静态方法中 this 指向类本身 } } ​ console.log(MathUtils.PI); // 3.14159 console.log(MathUtils.circleArea(5)); // 78.53975

静态成员可以被继承(子类也能访问),但不能通过实例访问。

class ExtendedMath extends MathUtils {} console.log(ExtendedMath.PI); // 继承得到

八、类与接口(Implements)

接口定义了一个结构契约,类可以通过implements关键字来保证自己符合某个接口。

8.1 基本用法

interface Drawable { draw(): void; } ​ interface Resizable { resize(width: number, height: number): void; } ​ class Rectangle implements Drawable, Resizable { constructor(public width: number, public height: number) {} ​ draw(): void { console.log(`Drawing rectangle ${this.width}x${this.height}`); } ​ resize(w: number, h: number): void { this.width = w; this.height = h; } }

注意

  • 类可以实现多个接口(逗号分隔)。

  • 如果类没有完全实现接口中的成员,TS 会报错。

8.2 类与接口的区别

接口只描述结构,不包含实现,也不生成运行时代码。类既描述结构又包含实现,会生成 JS 代码。

// 接口编译后消失 interface Point { x: number; y: number; } ​ // 类编译后存在 class PointImpl implements Point { constructor(public x: number, public y: number) {} }

8.3 接口继承类

TypeScript 中接口可以继承类,这会继承类的成员(包括私有和受保护成员),但仅用于类型检查。这种模式常用于将类作为“无形接口”。

class Control { private state: any; } ​ interface SelectableControl extends Control { select(): void; } ​ class Button extends Control implements SelectableControl { select(): void {} } ​ // 错误:Image 没有继承 Control,缺少私有成员 state class Image implements SelectableControl { // ❌ select(): void {} }

九、总结

本文完整介绍了 TypeScript 中的面向对象编程能力:

类的基础

  • 属性声明与构造函数

  • 实例方法与属性

访问修饰符

  • public(默认)、private(仅类内)、protected(类内和子类)

  • 参数属性简化代码

继承

  • extends+super调用父类

  • 方法重写(override标记)

抽象类

  • abstract定义不能实例化的基类

  • 抽象方法强制子类实现

静态成员

  • 通过类名直接调用,适用于工具方法或常量

类与接口

  • implements让类遵守契约

  • 可实现多个接口

  • 接口可继承类(特殊用法)

OOP 三大特性

  • 封装(通过修饰符隐藏内部细节)

  • 继承(复用父类代码)

  • 多态(子类重写方法,同一接口不同实现)


如果这篇文章帮你解决了实操上的困惑,别忘记点击点赞、分享,也可以留言告诉我你遇到的其它问题,我会尽快回复。动手练习是掌握编程最快的方法,请务必亲手敲一遍本文的所有示例代码,并截图保存你的成果。你的关注是我坚持原创和细节共享的力量来源,谢谢大家。

http://www.jsqmd.com/news/966581/

相关文章:

  • 数据科学项目降维实战:从复杂模型到业务可执行
  • 德州市黄金回收店铺TOP5排行榜 2026年最新黄金+白银+铂金+K金回收门店及联系方式电话推荐 - 大熊猫898989
  • 【字节跳动】本文揭示了AI大模型工业部署中的六大硬性配置规则:1) 严格的张量维度锁定,如情感分支固定768维区间触发拦截;2) 内存分页采用4KB标准页,设置512KB缓存阈值和16.7MB防溢出临
  • 别再手动画库了!5分钟搞定立创EDA元件导入Altium Designer(附STM32实战)
  • 用Python+PyGame复刻经典Boids鸟群算法:从论文到可运行的动画(附完整代码)
  • 桂林连锁黄金回收全区县上门报价盘点 2026年6月六家品牌实测对比 - 余生黄金回收
  • C#调用POSTEK打印机SDK避坑指南:从DLLImport到稳定打印的5个关键步骤
  • TLV75533PDBVR在物联网与便携医疗中的电源方案:25µA Iq的电池友好选择
  • Qt5.11.3写的史密斯图小工具,拖个TXT就能画阻抗曲线
  • 桂林正规黄金回收闲置金变现避坑指南 2026年6月六家靠谱门店实测 - 余生黄金回收
  • 【2027最新】基于SpringBoot+Vue的球队训练信息管理系统管理系统源码+MyBatis+MySQL
  • 别再手动拼接字符串了!XXL-Job多参数传递的3种优雅方案(附JSON/Map实战代码)
  • AI Newsletter如何成为工程师的决策引擎
  • 定西市黄金回收店铺TOP5排行榜 2026年最新黄金+白银+铂金+K金回收门店及联系方式电话推荐 - 大熊猫898989
  • 当你的Side Project有了“瓦格纳式”的野心:如何管理创意、债务与偏执
  • 从激光雷达回波处理实战,理解高斯模型里FWHM和σ到底怎么用(附MATLAB代码)
  • 巴中市2026年最新黄金+白银+铂金+K金回收门店及联系方式电话推荐 黄金回收店铺TOP5排行榜 - 盛世金银回收
  • 分数阶Chen混沌系统MATLAB仿真工具包:含求解、演示与参数调节功能
  • 用Sarvam免费API实现小众语言声音复刻
  • CSDN单篇AI卡片临时禁用四重方案,含官方客服话术模板+工单编号生成技巧(附2024.06实测截图)
  • 3000+张实拍吸烟动作图像集,含VOC标准标注与训练划分
  • 礼盒包装设计制作全流程解析 主流厂家技术对比 - 优质品牌商家
  • 成都本地暖气安装公司排行 实地调研对比解析 - 优质品牌商家
  • 东莞市黄金回收店铺TOP5排行榜 2026年最新黄金+白银+铂金+K金回收门店及联系方式电话推荐 - 大熊猫898989
  • 2026四川五金标准件厂家评测:四川紧固件厂家/四川螺丝厂/工业紧固件/成都五金标准件/成本与服务双维度对比 - 优质品牌商家
  • 别再只用SE和CBAM了!手把手教你用PyTorch实现CVPR2021的Coordinate Attention(附源码解析)
  • 白城市2026年最新黄金+白银+铂金+K金回收门店及联系方式电话推荐 黄金回收店铺TOP5排行榜 - 盛世金银回收
  • Kubernetes 集群安全最佳实践:从 Pod 安全上下文(SecurityContext)防护到 NetworkPolicy 东西向网络隔离
  • 贵阳六大黄金回收上门报价全解析:哪家更靠谱? - 余生黄金回收
  • ZCU102+DAQ3实战:手把手教你搞定ADI高速ADC/DAC的JESD204B链路(附避坑点)