Skip to content

类的继承 (Inheritance)

继承是面向对象编程(OOP)中的一个核心概念,它允许一个类(子类或派生类)从另一个类(父类或基类)继承属性和方法。通过继承,子类不仅可以复用父类的代码,还可以扩展或修改父类的行为,从而实现代码的重用性和灵活性。

在 TypeScript 中,继承是通过 extends 关键字来实现的,并且支持单继承(即一个子类只能继承自一个父类)。此外,TypeScript 还提供了 super 关键字,用于调用父类的构造函数和方法。

1. 基本概念

  • 父类(Base Class 或 Superclass):被继承的类。
  • 子类(Derived Class 或 Subclass):继承自父类的类。
  • extends 关键字:用于声明一个类继承自另一个类。
  • super 关键字:用于调用父类的构造函数和方法。

2. 语法

定义继承关系

typescript
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: 基本继承

typescript
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: 继承静态成员

typescript
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 调用父类方法

typescript
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() 调用了父类 Animalspeak 方法,然后添加了自己的行为。

4. 访问修饰符与继承

在 TypeScript 中,访问修饰符(如 publicprivateprotected)可以控制子类对父类成员的访问权限:

  • public:子类可以访问和修改父类的公共成员。
  • private:子类不能访问父类的私有成员。
  • protected:子类可以访问父类的受保护成员,但外部代码不能访问。

示例:访问修饰符与继承

typescript
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 类的 publicprotected 成员,但不能访问 private 成员。

5. 多态性

多态性是 OOP 的另一个重要特性,它允许子类对象作为父类对象处理。这使得你可以编写更加通用和灵活的代码。

示例:多态性

typescript
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 的成员是否在父类中存在,并且签名是否兼容。如果不存在或签名不匹配,编译器会报错。

语法

typescript
class Base {
  method() {
    console.log("Base method");
  }
}

class Derived extends Base {
  override method() {
    console.log("Derived method");
  }
}

在这个例子中,Derived 类中的 method 方法使用了 override 关键字,表明它是为了覆盖 Base 类中的同名方法。

6. 总结

继承是 TypeScript 和 JavaScript 中非常重要的特性,它允许你创建层次化的类结构,实现代码的重用和扩展。通过合理使用继承,你可以编写出更加模块化和可维护的代码。

Released under the MIT License.