TypeScript 中 'extends' 和 'implements' 有什么区别

What's the difference between 'extends' and 'implements' in TypeScript

我想知道ManChild 的共同点和不同点。

class Person {
  name: string;
  age: number;
}
class Child extends Person {}
class Man implements Person {}

简短版

  • extends表示:

新的class是child。它获得继承带来的好处。它具有 parent 的所有属性和方法。它可以覆盖其中的一些并实现新的,但是 parent 内容已经包含在内。

  • implements表示:

新的class可以当作一样的“形状”,但 它不是 child。它可以传递给任何需要 Person 的方法,无论 parent 与 Person.

不同

更多...

OOP(C# 或 Java 等语言)中,我们将使用

extendsinheritance.

中获利

... Inheritance in most class-based object-oriented languages is a mechanism in which one object acquires all the properties and behaviours of the parent object. Inheritance allows programmers to: create classes that are built upon existing classes ...

implements polymorphism.

会更多

... polymorphism is the provision of a single interface to entities of different types...

所以我们的 class Man:

可以有一个完全不同的继承树
class Man extends Human ...

但是如果我们也声明 Man 可以伪装成 Person 类型:

class Man extends Human 
          implements Person ...

...然后我们可以在任何需要 Person 的地方使用它。我们只需要实现 Person 的“接口”(即实现它的所有 public 内容)。

implement其他class?这真的很酷

Java脚本的漂亮面孔(好处之一)是 built-in 支持 duck typing

"If it walks like a duck and it quacks like a duck, then it must be a duck."

因此,在 Java 脚本中,如果两个不同的 object 具有一个相似的方法(例如 render()),则可以将它们传递给需要它的函数:

function(engine){
  engine.render() // any type implementing render() can be passed
}

为了不在 Typescript 中丢失它,我们可以通过更多的类型化支持来实现同样的目的。这就是

class implements class

有它的作用,在它有意义的地方。

在 OOP 语言中 C#,没办法做到这一点。

文档在这里应该有所帮助:

Interfaces Extending Classes

When an interface type extends a class type it inherits the members of the class but not their implementations. It is as if the interface had declared all of the members of the class without providing an implementation. Interfaces inherit even the private and protected members of a base class. This means that when you create an interface that extends a class with private or protected members, that interface type can only be implemented by that class or a subclass of it.

This is useful when you have a large inheritance hierarchy, but want to specify that your code works with only subclasses that have certain properties. The subclasses don’t have to be related besides inheriting from the base class. For example:

class Control {
    private state: any;
}

interface SelectableControl extends Control {
    select(): void;
}

class Button extends Control implements SelectableControl {
    select() { }
}

class TextBox extends Control {
    select() { }
}

// Error: Property 'state' is missing in type 'Image'.
class Image implements SelectableControl {
    private state: any;
    select() { }
}

class Location {

}

所以,虽然

  • extends 表示它从它的 parent
  • 中获取全部
  • implements 在这种情况下,它几乎就像实现一个接口。 child object 可以假装它是它的 parent... 但它没有得到任何实现。

您有 class打字稿(和其他一些面向对象语言)的实体和接口。

接口没有实现;这只是 members/method 这种类型所具有的“契约”。
例如:

interface Point {
    x: number;
    y: number;
    distance(other: Point): number;
}

实现此 Point 接口的实例必须有两个类型为数字的成员:xy', and one method, distance, which receives another Pointinstance and returns anumber`。
该接口未实现任何这些。

类 是实现:

class PointImplementation implements Point {
    public x: number;
    public y: number;
    
    constructor(x: number, y: number) {
        this.x = x;
        this.y = y;
    }
    
    public distance(other: Point): number {
        return Math.sqrt(Math.pow(this.x - other.x, 2) + Math.pow(this.y - other.y, 2));
    }
}

(code in playground)

在您的示例中,您在扩展时将 Person class 视为 class,在实现它时将其视为接口。
您的代码:

class Person {
    name: string;
    age: number;
}
class Child  extends Person {}

class Man implements Person {}

它有一个编译错误说:

Class 'Man' incorrectly implements interface 'Person'. Property' name' is missing in type 'Man'.

那是因为接口缺乏实现。
所以如果你 implement 一个 class,那么你只需要它的“合同”而没有实现,所以你需要这样做:

class NoErrorMan implements Person {
    name: string;
    age: number;
}

(code in playground)

最重要的是,在大多数情况下,您想要 extend 另一个 class 而不是 implement 它。

来自@nitzan-tomer 的出色回答!帮了我很多……我用以下方法扩展了他的演示:

IPoint interface;
Point implements IPoint;
Point3D extends Point;

以及它们在需要 IPoint 类型的函数中的行为方式。

到目前为止,我所学到的并一直作为经验法则使用:如果您正在使用 classes 和方法期望泛型类型,请使用接口作为期望类型。并确保父级或 base-class 使用该接口。这样你就可以使用所有子classes,只要它们实现了接口。

这里是extended demo

  1. 接口扩展接口形状
  2. 接口扩展 class 形状
  3. Class实现接口应该实现接口提供的所有字段
  4. Class 实现 class 形状
  5. Class 使用所有字段
  6. 扩展 class

extends 关注继承,implements 关注接口或 classes 的约束。

扩展VS工具

  • extends:childclass(扩展)将继承class的所有属性和方法] 是延伸
  • implements:使用implements关键字的class需要实现[=52]的所有属性和方法=] 它 implements

简单来说:

  • extends:这里你从parentclass得到所有这些methods/properties所以你不必自己实现
  • implements:这是class必须遵守的契约。 class 必须 实施 至少以下 methods/properties

示例:

class Person {
  name: string;
  age: number;

  walk(): void {
    console.log('Walking (person Class)')
  }

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}
class child extends Person { }

// Man has to implements at least all the properties
// and methods of the Person class
class man implements Person {
  name: string;
  age: number

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  walk(): void {
    console.log('Walking (man class)')
  }

}

(new child('Mike', 12)).walk();
// logs: Walking(person Class)

(new man('Tom', 12)).walk();
// logs: Walking(man class)

在示例中我们可以观察到 child class 继承了 Person 的所有内容,而 man class 必须实现 Person 本身的所有内容。

如果我们要从 man class 中删除一些东西,例如 walk 方法,我们将得到以下 编译时间 错误:

Class 'man' incorrectly implements class 'Person'. Did you mean to extend 'Person' and inherit its members as a subclass? Property 'walk' is missing in type 'man' but required in type 'Person'.(2720)

基本上:

  • extends 将获取父级 class 的所有属性和方法。
  • implements 将要求我们实现接口中定义的所有属性和方法。