您的位置:

深入理解TypeScript抽象类

一、什么是抽象类

抽象类是一种特殊的类,它不能被直接实例化,而是用来被继承的。它的定义使用abstract关键字,并且至少包含一个抽象方法。抽象方法需要在子类中被实现。


abstract class Animal {
  abstract makeSound(): void;
}

class Dog extends Animal {
  makeSound() {
    console.log("汪汪汪");
  }
}

const dog = new Dog();
dog.makeSound(); // 汪汪汪

在上述代码中,我们定义了一个抽象类Animal,其中包含了一个抽象方法makeSound。我们无法直接实例化Animal类,但是可以定义一个继承Animal类的Dog类,并实现makeSound方法。这里我们让Dog类输出汪汪汪。

二、抽象类的优点

抽象类相对于普通类的优点在于,它可以提供一种规范,强制子类必须实现某些方法。这对于约束项目中各个模块的行为非常有帮助。

例如,我们可以定义一个抽象类Person,它包含了一个抽象方法speak,用于输出个人的发言。然后我们可以定义两个子类,一个是Worker类,一个是Student类。Worker类的speak方法可以输出“I am working”,而Student类的speak方法可以输出“I am studying”。


abstract class Person {
  abstract speak(): void;
}

class Worker extends Person {
  speak() {
    console.log("I am working");
  }
}

class Student extends Person {
  speak() {
    console.log("I am studying");
  }
}

const worker = new Worker();
const student = new Student();
worker.speak(); // I am working
student.speak(); // I am studying

三、抽象类的实现原理

在编译后的JavaScript代码中,抽象类被实现为普通的类,只不过包含了一个特殊的__abstract属性,该属性用于标记某些方法是抽象方法。


var Animal = /** @class */ (function () {
  function Animal() {
  }
  return Animal;
}());

var Dog = /** @class */ (function (_super) {
  __extends(Dog, _super);
  function Dog() {
    return _super !== null && _super.apply(this, arguments) || this;
  }
  Dog.prototype.makeSound = function () {
    console.log("汪汪汪");
  };
  return Dog;
}(Animal));

var dog = new Dog();
dog.makeSound(); // 汪汪汪

通过上述编译后的代码可以看出,在Animal类中并没有包含任何的抽象方法,只是在定义Animal类时添加了一个__abstract属性,用于标记makeSound是抽象方法。在Dog类中,我们对makeSound方法做了具体的实现。

四、使用抽象类的注意点

抽象类虽然有很多优点,但是我们还是需要注意一些细节问题。

1. 如果一个类继承了抽象类,它必须实现该抽象类中的所有抽象方法,否则会报错。


abstract class Person {
  abstract speak(): void;
  abstract run(): void;
}

class Worker extends Person {
  speak() {
    console.log("I am working");
  }
  // 错误,Worker类没有实现run方法
}

class Student extends Person {
  speak() {
    console.log("I am studying");
  }
  run() {
    console.log("I am running");
  }
}

const worker = new Worker(); // 报错
const student = new Student();
student.run(); // I am running

2. 抽象方法不能有具体的实现,在抽象类中定义的方法只有名称和参数列表,没有方法体。


abstract class Person {
  abstract speak(): void {
    console.log("I am speaking");
  }
  // 错误,抽象方法不能有具体的实现
}

3. 抽象类也是可以被扩展的,我们可以继承一个抽象类,并在子类中实现它的抽象方法。这样,我们可以通过多重继承的方式来构建更加复杂的类和类层次。


abstract class Animal {
  abstract makeSound(): void;
}

abstract class Person {
  abstract speak(): void;
}

class Dog extends Animal {
  makeSound() {
    console.log("汪汪汪");
  }
}

class Student extends Person {
  speak() {
    console.log("I am studying");
  }
}

class WorkingDog extends Dog, Student {
  // WorkingDog同时继承了Dog和Student类,实现了makeSound和speak方法
}

const workingDog = new WorkingDog();
workingDog.makeSound(); // 汪汪汪
workingDog.speak(); // I am studying

五、总结

抽象类是一种很有用的语言特性,它可以为我们提供一种规范方式,强制子类实现一些必要的方法,从而提高代码的可读性和可维护性。

不过,在使用抽象类时,我们也需要注意一些细节问题,以避免出现代码错误和潜在的bug。