【问题标题】:What is the difference between interface and abstract class in Typescript?Typescript中的接口和抽象类有什么区别?
【发布时间】:2018-10-11 03:48:32
【问题描述】:

我写了几行代码来试验和区分这两者:interfaceabstract class

我发现他们有同样的限制。

interface IPerson {
  name: string;
  talk(): void;
}

interface IVIP {
  code: number;
}

abstract class Person {
  abstract name: string;
  abstract talk(): void;
}

class ManagerType1 extends Person {
  // The error I get is that I need to implement the talk() method
  // and name property from its base class.
}

class ManagerType2 implements IPerson {
  // The error I get is that I need to implement the talk() method 
  // and the name property from the interface.
}


class ManagerType3 implements IPerson, IVIP {
  // Now the error I get is that I need to implement all the 
  // properties and methods of the implemented interfaces to the derived class
}

正如我发现的那样,这两者之间没有明显的区别,因为它们都实现了相同的限制。我唯一注意到的是继承实现

  1. 一个类只能扩展为一个基类
  2. 一个类可以实现多个接口。

我没听错吗?如果是这样,我什么时候需要使用?

更新

我不知道这是否是正确的答案,但您可以根据自己的情况真正使用 BOTH。 OOP 真的很酷。

class ManagerType3 extends Person implements IPerson, IVIP {
  // Now the restriction is that you need to implement all the abstract
  // properties and methods in the base class and all 
  // the properties and methods from the interfaces
}

【问题讨论】:

  • 除了限制基类可以提供实现/部分实现,接口只定义shape/contract
  • @AlekseyL。是的,非常感谢,我发现接口是用于标准的,与抽象类相同,但是您可以为每个派生类添加一些持久的方法。

标签: typescript oop


【解决方案1】:

接口

interface一个合同,它定义了属性以及实现它的对象可以做什么。例如,您可以定义 PlumberElectrician 可以做什么:

interface Electrician {
  layWires(): void
}

interface Plumber {
  layPipes(): void
}

然后,您可以使用接口的服务:

function restoreHouse(e: Electrician, p: Plumber) {
  e.layWires()
  p.layPipes()
}

请注意,实现接口的方式是免费的。您可以通过实例化一个类或使用一个简单的对象来做到这一点:

let iAmAnElectrician = {
  layWires: () => { console.log("Work with wires…") }
}

接口在运行时根本不存在,因此无法进行自省。它是处理对象编程的经典 JavaScript 方式,但在定义的合约的编译时具有良好的控制。

抽象类

class 既是合同,也是工厂的实施abstract class 也是一个实现,但不完整。特别是在运行时存在抽象类,即使它只有抽象方法(那么instanceof可以使用)。

当您定义一个抽象类时,您通常会尝试控制必须如何实现流程。例如,你可以这样写:

abstract class HouseRestorer {
  protected abstract layWires(): void
  protected abstract layPipes(): void
  restoreHouse() {
    this.layWires()
    this.layPipes()
  }
}

这个抽象类HouseRestorer 定义了如何使用方法layWireslayPipes,但是在使用之前需要由子类来实现专门的处理。

抽象类是一种传统的 OOP 方法,这在 JavaScript 中并不传统。

这两种方法都允许做同样的事情。但它们是解决问题的两种不同方式。

【讨论】:

    【解决方案2】:

    TypeScript 的一个更大区别是(抽象)类在运行时可用,而接口仅在编译时可用。这意味着您不能将instanceof 与接口一起使用。

    let x: any;
    
    if (x instanceof IPerson) { // Error: 'IPerson' only refers to a type, but is being used as a value here.
    
    }
    
    if (x instanceof Person) { // OK
    
    }
    

    如果您真的不需要运行时类型,例如上面的示例,或者只想在具体类中实现,请选择接口。由于它们只是编译时的,所以生成的 JS 的大小会更小。

    【讨论】:

      猜你喜欢
      • 2010-12-27
      • 2010-12-12
      • 2010-11-13
      • 2013-02-17
      • 1970-01-01
      • 2012-04-28
      • 2019-12-14
      相关资源
      最近更新 更多