在TypeScript中,接口(Interface)和抽象类(Abstract Class)有什么区别?

67

我写了几行代码来实验和区分这两个东西:接口抽象类

我发现它们有相同的限制。

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. 一个类可以实现多个接口。

我理解的对吗?如果是这样,那么何时需要使用其中之一?

更新

我不知道这是否是正确答案,但你真的可以根据情况使用任何一种。面向对象编程真的很酷。

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
}

1
除了限制基类可以提供实现/部分实现外,接口仅定义形状/契约。 - Aleksey L.
@AlekseyL。是的,非常感谢,我弄清楚了接口是为标准而设计的,就像抽象类一样,但是您可以添加一些方法,这些方法对每个派生类都是持久的。 - Shift 'n Tab
可能是TypeScript中接口和类的区别的重复问题。 - Michael Freidgeim
3个回答

91

接口

接口是一个契约,它定义了实现它的对象的属性和能力。例如,您可以定义一个管道工和一个电工分别能做什么:

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,但需要一个子类来实现专门的处理才能使用。

抽象类是面向对象编程传统的一种方法,在JavaScript中不太传统。

两种方法都可以完成相同的事情。它们是解决问题的两种不同方式。


52

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文件大小将更小。


8

抽象类

  • Can't be used to create an object directly, because it does not have complete implementation

  • Only used as a parent class

  • An abstract class can implement one or more interface.

    interface Name {
       firstName: string
       lastName: string;
    }
    
    interface Work {
        doWork(): void;
    }
    
    abstract class BaseEmployee implements Name, Work {
      firstName: string;
      lastName: string;
    
      constructor(firstName: string, lastName: string) {
          this.firstName = firstName;
          this.lastName = lastName;
      }
    
      abstract doWork(): void;
    

    }

  • can contain real implementaion for some methods

  • the implemented methods can refer to other methods that do not actually exist yet( you still have to provide names and types for the unimplemented methods)

  • Abstract class compile to JavaScript functions.

接口

  • Unlike abstract classes, interfaces don’t implement methods or define a constructor and just define a shape. Interfaces are implemented by classes through the implements keyword

    class Student implements PersonInterface{}
    
  • Interfaces can be extended, just like classes. Abstract class are only parent

    interface Person {
          name: string;
          getDetails(): string;
       }
       interface CatOwner extends Person {
          catName: string;
          getCatDetails(): string;
       }
    
  • There is no JavaScript equivalent to interfaces, and no details of interfaces are included in the JavaScript code generated by the TypeScript compiler. This means that the instanceof keyword cannot be used to narrow interface types.


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接