文章目录
一、类的基本概念
类(Class)是面向对象编程的核心概念之一,在 TypeScript 中,类用于创建对象的蓝图或模板。它将数据(以属性的形式)和操作这些数据的函数(以方法的形式)组合在一起,使得代码的组织更加模块化、易于理解和维护。通过类,可以创建多个具有相同结构和行为的对象实例,这些实例共享类所定义的属性和方法,但又可以有各自独立的状态。
二、定义类(属性和方法)
使用 class 关键字来定义一个类,在类内部可以定义属性和方法。属性用于存储对象的数据,方法则是定义对象可以执行的操作。以下是一个简单的类定义示例:
class Person {
// 属性
name: string;
age: number;
// 方法
sayHello() {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
}
}
在上述 Person 类中,name 和 age 是属性,分别用于存储人的姓名和年龄信息,它们的数据类型被明确指定(string 和 number 类型)。sayHello 是一个方法,用于输出包含该对象 name 和 age 属性的问候语,在方法内部通过 this 关键字来访问当前对象的属性。
三、类的实例化
定义好类之后,需要通过实例化操作来创建具体的对象实例,语法是使用 new 关键字加上类名,并且可以在实例化时传入参数(如果类的构造函数有相应要求的话)。例如:
let person1 = new Person();
person1.name = "Alice";
person1.age = 25;
person1.sayHello(); // 输出 "Hello, my name is Alice and I'm 25 years old."
let person2 = new Person();
person2.name = "Bob";
person2.age = 30;
person2.sayHello(); // 输出 "Hello, my name is Bob and I'm 30 years old."
这里创建了两个 Person 类的实例 person1 和 person2,它们各自有独立的 name 和 age 属性值,但共享 sayHello 这个方法的定义。
四、类的继承
(一)extends 关键字(继承父类)
继承是面向对象编程中的一个重要特性,它允许创建一个新类(子类)基于现有的类(父类)进行扩展,子类会继承父类的属性和方法,从而实现代码的复用和层次化的类结构设计。在 TypeScript 中,使用 extends 关键字来实现继承。例如:
class Employee extends Person {
jobTitle: string;
constructor(name: string, age: number, jobTitle: string) {
super(name, age);
this.jobTitle = jobTitle;
}
introduceJob() {
console.log(`I'm ${this.name} and I work as a ${this.jobTitle}.`);
}
}
在上述示例中,Employee 类继承自 Person 类,这意味着 Employee 类的实例不仅拥有 Person 类中定义的 name 和 age 属性以及 sayHello 方法,还额外定义了自己的属性 jobTitle 和方法 introduceJob。在 Employee 类的构造函数中,需要先调用 super 关键字来调用父类的构造函数,以确保父类的属性能够正确初始化。
五、方法重写(在子类中重新定义父类的方法)
有时候,子类可能需要对父类中已有的方法进行重新定义,以满足子类特定的需求,这就是方法重写。重写时,子类中的方法签名(方法名、参数列表、返回值类型等)要与父类被重写的方法基本一致(返回值类型如果是协变类型可以有所不同,但这里暂不深入探讨复杂情况),只是方法体的逻辑会改变。例如:
class Manager extends Employee {
managePeople() {
console.log(`I'm ${this.name} and I manage a team.`);
}
sayHello() {
console.log(`Hello, I'm ${this.name}, the manager.`);
}
}
let manager = new Manager("Charlie", 40, "Manager");
manager.sayHello(); // 输出 "Hello, I'm Charlie, the manager.",调用的是重写后的 sayHello 方法
manager.introduceJob(); // 输出 "I'm Charlie and I work as a Manager.",调用的是从 Employee 类继承来的 introduceJob 方法
在 Manager 类中对 sayHello 方法进行了重写,当 Manager 类的实例调用 sayHello 方法时,执行的是重写后的逻辑,而不是从父类 Employee 继承来的原始 sayHello 方法。
六、访问修饰符
(一)public(公开访问)
public 是默认的访问修饰符,如果属性或方法前面没有显式地添加访问修饰符,那它就是 public 的。这意味着它们可以在类的内部、子类以及类的外部都能被访问。例如,前面定义的 Person 类中的属性和方法都是默认 public 的,可以像下面这样在类外部访问:
let person = new Person();
person.name = "David";
person.age = 35;
person.sayHello();
(二)private(私有访问,只能在类内部访问)
使用 private 修饰符声明的属性或方法,只能在其所属的类内部被访问,在子类以及类的外部都无法访问,这有助于对类内部的数据和操作进行封装,避免外部的不当访问和修改。例如:
class Secret {
private password: string;
constructor(password: string) {
this.password = password;
}
checkPassword(input: string) {
return this.password === input;
}
}
let secret = new Secret("123456");
// secret.password; // 编译错误,无法在类外部访问 private 属性
secret.checkPassword("123456"); // 合法,在类内部可以使用 private 属性进行操作
(三)protected(受保护访问,在类和子类中访问)
protected 修饰符声明的属性或方法,可以在类内部以及其子类中被访问,但在类的外部是无法访问的。它在 public 和 private 之间提供了一种适中的访问控制级别,常用于在继承体系中让子类能够访问父类的部分属性或方法,同时又限制外部的访问。例如:
class Parent {
protected familyName: string;
constructor(familyName: string) {
this.familyName = familyName;
}
}
class Child extends Parent {
constructor(familyName: string) {
super(familyName);
console.log(this.familyName); // 合法,在子类中可以访问 protected 属性
}
}
let child = new Child("Smith");
// child.familyName; // 编译错误,在类外部无法访问 protected 属性
通过合理运用类以及相关的继承、方法重写和访问修饰符等特性,可以构建出结构清晰、具有良好封装性和扩展性的面向对象程序,提高代码的可维护性和复用性。