类的继承 (Inheritance)
继承是面向对象编程(OOP)中的一个核心概念,它允许一个类(子类或派生类)从另一个类(父类或基类)继承属性和方法。通过继承,子类不仅可以复用父类的代码,还可以扩展或修改父类的行为,从而实现代码的重用性和灵活性。
在 TypeScript 中,继承是通过 extends 关键字来实现的,并且支持单继承(即一个子类只能继承自一个父类)。此外,TypeScript 还提供了 super 关键字,用于调用父类的构造函数和方法。
1. 基本概念
- 父类(Base Class 或 Superclass):被继承的类。
- 子类(Derived Class 或 Subclass):继承自父类的类。
extends关键字:用于声明一个类继承自另一个类。super关键字:用于调用父类的构造函数和方法。
2. 语法
定义继承关系
class Animal {
constructor(public name: string) {}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Dog extends Animal {
constructor(name: string, public breed: string) {
super(name); // 调用父类的构造函数
}
speak() {
console.log(`${this.name} barks.`);
}
}
const dog = new Dog("Rex", "German Shepherd");
dog.speak(); // 输出: Rex barks.在这个例子中,Dog 类继承了 Animal 类,并重写了 speak 方法以提供更具体的行为。
3. 示例解析
示例 1: 基本继承
class Person {
constructor(public name: string, public age: number) {}
introduce() {
console.log(
`Hello, my name is ${this.name} and I am ${this.age} years old.`
);
}
}
class Employee extends Person {
constructor(name: string, age: number, public position: string) {
super(name, age);
}
work() {
console.log(`${this.name} works as a ${this.position}.`);
}
}
const employee = new Employee("Alice", 30, "Developer");
employee.introduce(); // 输出: Hello, my name is Alice and I am 30 years old.
employee.work(); // 输出: Alice works as a Developer.在这个例子中,Employee 类继承了 Person 类,并添加了一个新的属性 position 和一个新的方法 work。
示例 2: 继承静态成员
class BaseClass {
static baseProperty: string = "I am a static property";
static baseMethod() {
console.log("I am a static method.");
}
}
class DerivedClass extends BaseClass {
static derivedProperty: string = "I am a derived static property";
static derivedMethod() {
console.log("I am a derived static method.");
}
}
console.log(BaseClass.baseProperty); // 输出: I am a static property
BaseClass.baseMethod(); // 输出: I am a static method.
console.log(DerivedClass.baseProperty); // 输出: I am a static property
DerivedClass.baseMethod(); // 输出: I am a static method.
console.log(DerivedClass.derivedProperty); // 输出: I am a derived static property
DerivedClass.derivedMethod(); // 输出: I am a derived static method.在这个例子中,DerivedClass 继承了 BaseClass 的静态属性和静态方法,并定义了自己的静态属性和静态方法。
示例 3: 使用 super 调用父类方法
class Animal {
constructor(public name: string) {}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Cat extends Animal {
constructor(name: string, public color: string) {
super(name);
}
speak() {
super.speak(); // 调用父类的方法
console.log(`${this.name} meows.`);
}
}
const cat = new Cat("Whiskers", "white");
cat.speak();
// 输出:
// Whiskers makes a noise.
// Whiskers meows.在这个例子中,Cat 类使用 super.speak() 调用了父类 Animal 的 speak 方法,然后添加了自己的行为。
4. 访问修饰符与继承
在 TypeScript 中,访问修饰符(如 public、private 和 protected)可以控制子类对父类成员的访问权限:
public:子类可以访问和修改父类的公共成员。private:子类不能访问父类的私有成员。protected:子类可以访问父类的受保护成员,但外部代码不能访问。
示例:访问修饰符与继承
class Base {
public publicProperty: string = "Public";
private privateProperty: string = "Private";
protected protectedProperty: string = "Protected";
publicMethod() {
console.log(this.publicProperty);
}
privateMethod() {
console.log(this.privateProperty);
}
protectedMethod() {
console.log(this.protectedProperty);
}
}
class Derived extends Base {
accessProperties() {
console.log(this.publicProperty); // OK
// console.log(this.privateProperty); // Error: 'privateProperty' is private
console.log(this.protectedProperty); // OK
}
callMethods() {
this.publicMethod(); // OK
// this.privateMethod(); // Error: 'privateMethod' is private
this.protectedMethod(); // OK
}
}在这个例子中,Derived 类可以访问和调用 Base 类的 public 和 protected 成员,但不能访问 private 成员。
5. 多态性
多态性是 OOP 的另一个重要特性,它允许子类对象作为父类对象处理。这使得你可以编写更加通用和灵活的代码。
示例:多态性
class Animal {
speak(): void {
console.log("An animal makes a noise.");
}
}
class Dog extends Animal {
speak(): void {
console.log("A dog barks.");
}
}
class Cat extends Animal {
speak(): void {
console.log("A cat meows.");
}
}
function makeNoise(animal: Animal) {
animal.speak();
}
const dog = new Dog();
const cat = new Cat();
makeNoise(dog); // 输出: A dog barks.
makeNoise(cat); // 输出: A cat meows.在这个例子中,makeNoise 函数接受一个 Animal 类型的参数,但它可以处理任何继承自 Animal 的子类对象,展示了多态性的优势。
7. override 关键字
override 关键字是 TypeScript 4.3 引入的一个特性,用于明确标识一个类成员(方法或属性)是在重写父类中的同名成员。使用 override 可以提高代码的可读性和类型安全性,确保子类中定义的方法确实存在于父类中,并且签名匹配。
基本概念
override:用于标记子类中的方法或属性是为了覆盖父类中的同名成员。- 类型检查:TypeScript 编译器会检查被标记为
override的成员是否在父类中存在,并且签名是否兼容。如果不存在或签名不匹配,编译器会报错。
语法
class Base {
method() {
console.log("Base method");
}
}
class Derived extends Base {
override method() {
console.log("Derived method");
}
}在这个例子中,Derived 类中的 method 方法使用了 override 关键字,表明它是为了覆盖 Base 类中的同名方法。
6. 总结
继承是 TypeScript 和 JavaScript 中非常重要的特性,它允许你创建层次化的类结构,实现代码的重用和扩展。通过合理使用继承,你可以编写出更加模块化和可维护的代码。