Appearance
TypeScript 面向对象:Class 与 TS
TypeScript 支持面向对象编程,本章节将介绍 TypeScript 中的类(Class)相关特性,包括类的定义、构造函数、修饰符、只读属性、静态属性、类实现接口、抽象类等。
类的定义
使用 class 关键字定义类:
示例:
typescript
// 定义一个类
class Person {
// 属性
name: string;
age: number;
// 构造函数
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
// 方法
sayHello(): void {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
}
// 方法
getBirthYear(): number {
const currentYear = new Date().getFullYear();
return currentYear - this.age;
}
}
// 创建类的实例
const person = new Person("John", 30);
// 访问属性
console.log(person.name); // John
console.log(person.age); // 30
// 调用方法
person.sayHello(); // Hello, my name is John and I'm 30 years old.
console.log(person.getBirthYear()); // 1994 (假设当前是2024年)构造函数
构造函数是类的特殊方法,在创建类的实例时自动调用:
示例:
typescript
class Car {
brand: string;
model: string;
year: number;
// 构造函数
constructor(brand: string, model: string, year: number) {
this.brand = brand;
this.model = model;
this.year = year;
}
// 方法
getCarInfo(): string {
return `${this.year} ${this.brand} ${this.model}`;
}
}
// 创建实例
const car = new Car("Toyota", "Corolla", 2020);
console.log(car.getCarInfo()); // 2020 Toyota Corolla
// 构造函数参数可以有默认值
class Person {
name: string;
age: number;
constructor(name: string, age: number = 18) {
this.name = name;
this.age = age;
}
}
const person1 = new Person("John"); // age 默认为 18
const person2 = new Person("Jane", 25); // age 为 25修饰符
TypeScript 提供了三种访问修饰符:
public:公共的,可以在任何地方访问(默认)private:私有的,只能在类内部访问protected:受保护的,可以在类内部和子类中访问
示例:
typescript
class Person {
// 公共属性
public name: string;
// 私有属性
private age: number;
// 受保护属性
protected gender: string;
constructor(name: string, age: number, gender: string) {
this.name = name;
this.age = age;
this.gender = gender;
}
// 公共方法
public sayHello(): void {
console.log(`Hello, my name is ${this.name}`);
this.logAge(); // 可以在类内部访问私有方法
}
// 私有方法
private logAge(): void {
console.log(`I'm ${this.age} years old`);
}
// 受保护方法
protected logGender(): void {
console.log(`I'm ${this.gender}`);
}
}
class Employee extends Person {
constructor(name: string, age: number, gender: string) {
super(name, age, gender);
}
public introduce(): void {
console.log(`Hi, I'm ${this.name}`);
// this.logAge(); // 错误:不能访问私有方法
this.logGender(); // 可以访问受保护方法
}
}
// 使用
const person = new Person("John", 30, "male");
console.log(person.name); // 正确:可以访问公共属性
// console.log(person.age); // 错误:不能访问私有属性
// console.log(person.gender); // 错误:不能访问受保护属性
person.sayHello(); // 正确:可以调用公共方法
// person.logAge(); // 错误:不能调用私有方法
// person.logGender(); // 错误:不能调用受保护方法
const employee = new Employee("Jane", 25, "female");
employee.introduce(); // 正确:可以调用公共方法只读属性
使用 readonly 关键字标记只读属性:
示例:
typescript
class Person {
// 只读属性
readonly id: number;
name: string;
constructor(id: number, name: string) {
this.id = id;
this.name = name;
}
// 方法
updateName(newName: string): void {
this.name = newName; // 正确:可以修改普通属性
// this.id = 2; // 错误:不能修改只读属性
}
}
// 使用
const person = new Person(1, "John");
console.log(person.id); // 1
console.log(person.name); // John
person.updateName("Jane");
console.log(person.name); // Jane
// person.id = 2; // 错误:不能修改只读属性静态属性
使用 static 关键字定义静态属性和方法:
示例:
typescript
class MathUtil {
// 静态属性
static PI: number = 3.14159;
// 静态方法
static add(a: number, b: number): number {
return a + b;
}
static multiply(a: number, b: number): number {
return a * b;
}
}
// 访问静态属性
console.log(MathUtil.PI); // 3.14159
// 调用静态方法
console.log(MathUtil.add(1, 2)); // 3
console.log(MathUtil.multiply(2, 3)); // 6
// 静态属性和方法也可以有访问修饰符
class Config {
private static apiKey: string = "secret-key";
public static getApiKey(): string {
return this.apiKey;
}
}
// console.log(Config.apiKey); // 错误:不能访问私有静态属性
console.log(Config.getApiKey()); // secret-key类实现接口
使用 implements 关键字让类实现接口:
示例:
typescript
// 定义接口
interface Animal {
name: string;
makeSound(): void;
}
// 实现接口
class Dog implements Animal {
name: string;
constructor(name: string) {
this.name = name;
}
makeSound(): void {
console.log("Woof!");
}
}
class Cat implements Animal {
name: string;
constructor(name: string) {
this.name = name;
}
makeSound(): void {
console.log("Meow!");
}
}
// 使用
const dog = new Dog("Rex");
dog.makeSound(); // Woof!
const cat = new Cat("Whiskers");
cat.makeSound(); // Meow!
// 实现多个接口
interface Flyable {
fly(): void;
}
interface Swimmable {
swim(): void;
}
class Duck implements Animal, Flyable, Swimmable {
name: string;
constructor(name: string) {
this.name = name;
}
makeSound(): void {
console.log("Quack!");
}
fly(): void {
console.log("Duck is flying");
}
swim(): void {
console.log("Duck is swimming");
}
}
const duck = new Duck("Donald");
duck.makeSound(); // Quack!
duck.fly(); // Duck is flying
duck.swim(); // Duck is swimming抽象类
使用 abstract 关键字定义抽象类:
示例:
typescript
// 定义抽象类
abstract class Shape {
// 抽象属性
abstract name: string;
// 普通方法
getArea(): number {
return 0;
}
// 抽象方法(必须在子类中实现)
abstract calculateArea(): number;
}
// 继承抽象类
class Circle extends Shape {
name: string = "Circle";
radius: number;
constructor(radius: number) {
super();
this.radius = radius;
}
// 实现抽象方法
calculateArea(): number {
return Math.PI * this.radius * this.radius;
}
}
class Rectangle extends Shape {
name: string = "Rectangle";
width: number;
height: number;
constructor(width: number, height: number) {
super();
this.width = width;
this.height = height;
}
// 实现抽象方法
calculateArea(): number {
return this.width * this.height;
}
}
// 使用
const circle = new Circle(5);
console.log(`${circle.name} area: ${circle.calculateArea()}`); // Circle area: 78.53981633974483
const rectangle = new Rectangle(4, 6);
console.log(`${rectangle.name} area: ${rectangle.calculateArea()}`); // Rectangle area: 24
// 不能实例化抽象类
// const shape = new Shape(); // 错误:Cannot create an instance of an abstract class实战:TS 面向对象案例
示例:学生管理系统
typescript
// 定义接口
interface Person {
id: number;
name: string;
age: number;
}
interface Student extends Person {
studentId: string;
grade: string;
courses: Course[];
enrollCourse(course: Course): void;
getGPA(): number;
}
interface Course {
id: number;
name: string;
credits: number;
grade?: number;
}
// 实现 Course 类
class CourseImpl implements Course {
id: number;
name: string;
credits: number;
grade?: number;
constructor(id: number, name: string, credits: number) {
this.id = id;
this.name = name;
this.credits = credits;
}
}
// 实现 Student 类
class StudentImpl implements Student {
id: number;
name: string;
age: number;
studentId: string;
grade: string;
courses: Course[] = [];
constructor(id: number, name: string, age: number, studentId: string, grade: string) {
this.id = id;
this.name = name;
this.age = age;
this.studentId = studentId;
this.grade = grade;
}
enrollCourse(course: Course): void {
this.courses.push(course);
}
getGPA(): number {
if (this.courses.length === 0) {
return 0;
}
const totalPoints = this.courses.reduce((sum, course) => {
const grade = course.grade || 0;
return sum + (grade * course.credits);
}, 0);
const totalCredits = this.courses.reduce((sum, course) => {
return sum + course.credits;
}, 0);
return totalPoints / totalCredits;
}
}
// 使用
const mathCourse = new CourseImpl(1, "Mathematics", 3);
const englishCourse = new CourseImpl(2, "English", 3);
const scienceCourse = new CourseImpl(3, "Science", 4);
const student = new StudentImpl(1, "John", 16, "S12345", "10th Grade");
student.enrollCourse(mathCourse);
student.enrollCourse(englishCourse);
student.enrollCourse(scienceCourse);
// 设置成绩
mathCourse.grade = 95;
englishCourse.grade = 88;
scienceCourse.grade = 92;
console.log(`Student: ${student.name}`);
console.log(`Student ID: ${student.studentId}`);
console.log(`Grade: ${student.grade}`);
console.log(`Courses enrolled: ${student.courses.length}`);
console.log(`GPA: ${student.getGPA().toFixed(2)}`);小结
本章节介绍了 TypeScript 中的面向对象编程特性,包括:
- 类的定义
- 构造函数
- 修饰符:public / private / protected
- 只读属性 readonly
- 静态属性 static
- 类实现接口 implements
- 抽象类 abstract
- 实战:TS 面向对象案例
TypeScript 的面向对象特性可以帮助你构建更结构化、更可维护的代码,特别是在大型项目中。通过使用类、接口、抽象类等特性,你可以创建清晰的代码结构,提高代码的可复用性和可维护性。
在实际开发中,应该根据具体需求选择合适的面向对象特性,以构建高质量的 TypeScript 代码。
