TypeScript 中的“扩展”和“实现”有什么区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38834625/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 07:16:26  来源:igfitidea点击:

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

typescriptextendsimplements

提问by davejoem

I would like to know what manand childhave in common and how they differ.

我想知道男人孩子有什么共同点,他们有什么不同。

class Person {
  name: string;
  age: number;
}
class child extends Person {}
class man implements Person {}

回答by Radim K?hler

Short version

精简版

  • extendsmeans:
  • extends方法:

The new class is a child. It gets benefits coming with inheritance. It has all properties, methods as its parent. It can override some of these and implement new, but the parent stuff is already included.

新类是孩子。它通过继承获得好处。它具有作为其父级的所有属性和方法。它可以覆盖其中的一些并实现新的,但已经包含了父级的东西。

  • implementsmeans:
  • implements方法:

The new classcan be treated as the same "shape", while it is not a child. It could be passed to any method where the Personis required, regardless of having different parent than Person

新类可视为同一“形”,而这是不是一个孩子。它可以传递给任何需要的方法Person,无论父级与Person

More ...

更多的 ...

In OOP(languages like C#, Java)we would use

OOP (C#、Java 等语言)中,我们会使用

extendsto profit from inheritance (see wiki). Small cite:

extends从继承中获利(参见wiki)。小引用:

... 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 ...

... 大多数基于类的面向对象语言中的继承是一种机制,其中一个对象获取父对象的所有属性和行为。继承允许程序员:创建基于现有类的类......

implementswill be more for polymorphism (see wiki). Small cite:

implements多态性会更多(参见wiki)。小引用:

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

...多态是为不同类型的实体提供单一接口...

So, we can have really different inheritance tree of our class Man.

因此,我们可以拥有真正不同的class Man.

class Man extends Human ...

but if we also declare that we can pretend to be a different type - Person:

但是如果我们也声明我们可以假装是不同的类型 - Person

class Man extends Human 
          implements Person ...

.. then we can use it anywhere, where the Personis required. We just have to fulfill Persons's "interface"(i.e. implement all its public stuff).

.. 然后我们可以在任何Person需要的地方使用它。我们只需要实现 Person 的"interface"(即实现其所有公共内容)

implementother class? That is really cool stuff

implement别的班?这真是很酷的东西

Javascript nice face (one of the benefits)is the built-in support of the Duck typing (see wiki). Small cite:

Javascript 漂亮的面孔(好处之一)是对 Duck 类型的内置支持(请参阅 wiki)。小引用:

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

“如果它走路像鸭子,叫起来像鸭子,那它一定是只鸭子。”

So, in Javascript, if two different objects... would have one similar method (e.g. render())they can be passed to a function which expects it:

所以,在 Javascript 中,如果两个不同的对象......会有一个类似的方法(例如render()),它们可以传递给一个期望它的函数:

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

To not lose that - we can in Typescript do the same - with more typed support. And that is where

为了不失去这一点 - 我们可以在 Typescript 中做同样的事情 - 有更多的类型支持。那就是

class implements class

has its role, where it makes sense

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

In OOP languages as C#... no way to do that...

在 OOP 语言中C#……没有办法做到这一点……

Also The documentation should help here:

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

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 {
    select() { }
}

class TextBox extends Control {
    select() { }
}

class Image extends Control {
}

class Location {
    select() { }
}

接口扩展类

当接口类型扩展类类型时,它继承类的成员而不是它们的实现。就好像接口在没有提供实现的情况下声明了类的所有成员。接口甚至继承基类的私有成员和受保护成员。这意味着当您创建一个接口来扩展具有私有或受保护成员的类时,该接口类型只能由该类或其子类实现。

当您拥有大型继承层次结构,但希望指定您的代码仅适用于具有某些属性的子类时,这很有用。除了从基类继承之外,子类不必相关。例如:

class Control {
    private state: any;
}

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

class Button extends Control {
    select() { }
}

class TextBox extends Control {
    select() { }
}

class Image extends Control {
}

class Location {
    select() { }
}

So, while

所以,同时

  • extendsmeans - it gets all from its parent
  • implementsin this case is almost like implementing an interface. Child object can pretend that it is parent... but it does not get any implementation
  • extends意味着 - 它从其父级获取所有
  • implements在这种情况下几乎就像实现一个接口。子对象可以假装它是父对象......但它没有得到任何实现

回答by Nitzan Tomer

In typescript (and some other OO languages) you have classes and interfaces.

在打字稿(和其他一些面向对象语言)中,您有类和接口。

An interface has no implementation, it's just a "contract" of what members/method this type has.
For example:

接口没有实现,它只是此类型具有的成员/方法的“合同”。
例如:

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

Instances who implement this Pointinterface must have two members of type number: xand y, and one method distancewhich receives another Pointinstance and returns a number.
The interface doesn't implement any of those.

实现这个Point接口的实例必须有两个 number 类型的成员:xand y,一个方法distance接收另一个Point实例并返回一个number
该接口没有实现任何这些。

Classes are the implementations:

类是实现:

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)

操场上的代码

In your example you treat your Personclass once as a class when you extend it and once as an interface when you implement it.
Your code:

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

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

class Man implements Person {}

Has a compilation error saying:

有一个编译错误说:

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

“Man”类错误地实现了“Person”接口。
“Man”类型中缺少属性“name”。

And that's because interfaces lack implementation.
So if you implementa class then you only take its "contract" without the implementation, so you'll need to do this:

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

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

(code in playground)

操场上的代码

Bottom line is that in most cases you want to extendanother class and not to implementit.

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

回答by andzep

Great Answer from @nitzan-tomer! Helped me a lot... I extended his demo a bit with:

来自@nitzan-tomer 的好答案!帮了我很多……我扩展了他的演示:

IPoint interface;
Point implements IPoint;
Point3D extends Point;

And how they behave in functions expecting an IPointtype.

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

So what I've learned so far and been using as a thumb-rule: If you're using classes and methods expecting generic types, use interfaces as the expected types. And make sure the parent or base-class uses that interface. That way you can use all subclasses in those as far as they implement the interface.

所以到目前为止我所学到的并一直用作拇指规则:如果您使用需要泛型类型的类和方法,请使用接口作为预期类型。并确保父类或基类使用该接口。这样你就可以使用这些子类中的所有子类,只要它们实现了接口。

Here the extended demo

这里是扩展演示

回答by lei li

  1. Interface extends interface with shape
  2. Interface extends class with shape
  3. Class implements interface should implements all fields provided by the interface
  4. Class implements class with shape
  5. Class extends class with all fields
  1. 界面通过形状扩展界面
  2. 接口用形状扩展类
  3. 类实现接口应该实现接口提供的所有字段
  4. 类实现具有形状的类
  5. 类使用所有字段扩展类

extendsfocus on inherit and implementsfocus on constraint whether interfaces or classes.

extends关注继承,implements关注约束,无论是接口还是类。