接口和Typescript中的抽象类有什么区别?

Roe*_*oel 10 oop typescript

我编写了几行代码来进行实验并区分这两个: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 derive class
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

更新

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

class ManagerType3 extends Person implements IPerson, IVIP {
  // Now the restriction is you need to implement all the abstract
  // properties and methods in the based class and all 
  // the properties and methods from the interfaces
}
Run Code Online (Sandbox Code Playgroud)

Wic*_*koo 12

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

}
Run Code Online (Sandbox Code Playgroud)

如果您确实不需要运行时类型(如上面的示例),或者只想在具体类中实现,请使用接口。由于它们仅是编译时,因此生成的JS的大小将较小。


Pal*_*leo 11

介面

An interface是定义属性以及实现它的对象可以做什么的合同。例如,您可以定义什么可以做水管工电工

interface Electrician {
  layWires(): void
}

interface Plumber {
  layPipes(): void
}
Run Code Online (Sandbox Code Playgroud)

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

function restoreHouse(e: Electrician, p: Plumber) {
  e.layWires()
  p.layPipes()
}
Run Code Online (Sandbox Code Playgroud)

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

let iAmAnElectrician = {
  layWires: () => { console.log("Work with wires…") }
}
Run Code Online (Sandbox Code Playgroud)

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

抽象类

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

定义抽象类时,通常会尝试控制流程的实现方式。例如,您可以这样写:

abstract class HouseRestorer {
  protected abstract layWires(): void
  protected abstract layPipes(): void
  restoreHouse() {
    this.layWires()
    this.layPipes()
  }
}
Run Code Online (Sandbox Code Playgroud)

此抽象类HouseRestorer定义了如何的方法layWireslayPipes将被使用,但它是由一个子类来实现专业治疗,然后才能使用它。

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

两种方法都允许完成相同的操作。但是它们是解决问题的两种不同方式。这并不意味着他们彼此值得。


Yil*_*maz 8

抽象类

\n
    \n
  • 不能直接用来创建对象,因为它没有完整的实现

    \n
  • \n
  • 仅用作父类

    \n
  • \n
  • 抽象类可以实现一个或多个接口。

    \n
    interface Name {\n   firstName: string\n   lastName: string;\n}\n\ninterface Work {\n    doWork(): void;\n}\n\nabstract class BaseEmployee implements Name, Work {\n  firstName: string;\n  lastName: string;\n\n  constructor(firstName: string, lastName: string) {\n      this.firstName = firstName;\n      this.lastName = lastName;\n  }\n\n  abstract doWork(): void;\n
    Run Code Online (Sandbox Code Playgroud)\n

    }

    \n
  • \n
  • 可以包含某些方法的实际实现

    \n
  • \n
  • 已实现的方法可以引用其他实际尚不存在的方法(您仍然需要为未实现的方法提供名称和类型)

    \n
  • \n
  • 抽象类编译为 JavaScript 函数。

    \n
  • \n
\n

界面

\n
    \n
  • 与抽象类不同,接口不实现方法或定义构造函数,而只定义形状。接口由类通过implements关键字实现

    \n
    class Student implements PersonInterface{}\n
    Run Code Online (Sandbox Code Playgroud)\n
  • \n
  • 接口可以像类一样进行扩展。抽象类只是父类

    \n
    interface Person {\n      name: string;\n      getDetails(): string;\n   }\n   interface CatOwner extends Person {\n      catName: string;\n      getCatDetails(): string;\n   }\n
    Run Code Online (Sandbox Code Playgroud)\n
  • \n
  • 没有与接口等效的 JavaScript,并且 TypeScript 编译器生成的 JavaScript 代码中不包含接口的详细信息。这意味着该instanceof关键字不能用于缩小接口类型。

    \n
  • \n
\n


Eve*_*ert 5

您是正确的,但是第二个区别是抽象类可以具有方法实现。