'延伸'之间的区别是什么?并且'实现'在TypeScript中

时间:2016-08-08 16:49:59

标签: typescript extends implements

我想知道 man 孩子 有什么共同之处,以及它们的区别。

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

5 个答案:

答案 0 :(得分:74)

短版

  • extends 表示:

新班级是孩子。继承带来好处。它具有所有属性,方法作为其父级。它可以覆盖其中的一些并实现new,但父内容已经包含在内。

  • implements 表示:

新班级可以被视为相同的“形状” ,而它不是孩子 。它可以传递给任何需要Person的方法,无论父级是否与Person不同

更多......

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

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

  

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

对于多态性,

implements 会更多(请参阅wiki)。小引用:

  

... polymorphism是为不同类型的实体提供单个接口...

因此,我们可以拥有真正不同的class Man继承树。

class Man extends Human ...

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

class Man extends Human 
          implements Person ...

..然后我们可以在需要Person的任何地方使用它。我们只需要履行人员"interface" (即实施所有公共资料)

implement其他课程?这真是很酷的东西

Javascript nice face (其中一个好处)是Duck输入(see wiki)的内置支持。小引用:

  

“如果它像鸭子一样走路,它像鸭子一样嘎嘎叫,那它一定是鸭子。”

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

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

为了不丢失 - 我们可以在Typescript中做同样的事情 - 使用更多类型的支持。那就是

class implements class

有其作用,有意义

在OOP语言中C# ......无法做到这一点......

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

  

Interfaces Extending Classes

     

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

     

当您具有较大的继承层次结构但需要时,这很有用   指定您的代码仅适用于具有某些子类的子类   属性。除继承之外,子类不必相关   来自基类。例如:

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

所以,而

  • extends表示 - 它从其父
  • 获取所有内容 在这种情况下,
  • implements几乎就像实现一个接口。子对象可以假装它是父...但它没有得到任何实现

答案 1 :(得分:61)

在typescript(和其他一些OO语言)中,您有类和接口。

界面没有实现,它只是一个"合同"这种类型的成员/方法有哪些 例如:

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

实现此Point接口的实例必须有两个类型为xy的成员,以及一个接收另一个distance实例的方法Point并返回number
界面没有实现其中任何一个。

类是实现:

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 Person {
    name: string;
    age: number;
}
class Child  extends Person {}

class Man implements Person {}

编译错误说:

  

班级'男人'错误地实现了界面' Person'   财产名称'类型' Man'

中缺少

那是因为接口缺乏实施 所以,如果你implement一个班级,那么你只需要它的#34;合同"没有实施,所以你需要这样做:

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

code in playground

最重要的是,在大多数情况下,你想要extend另一个班级,而不是implement

答案 2 :(得分:6)

扩展了VS工具

  • extends:子类(已扩展)将继承该类的所有属性和方法都被扩展
  • implements:使用implements关键字的类将需要实现该类implements
  • 的所有属性和方法

简单地说:

  • extends:在这里,您可以从父类中获得所有这些方法/属性,因此您不必自己实现
  • implements:这是全班必须遵守的合同。该类必须至少实现以下方法/属性

示例:

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)

在该示例中,我们可以观察到子类继承了Person的所有内容,而man类不得不实现了Person本身的所有内容。

如果要从man类中删除某些内容(例如walk方法),则会收到以下编译时间错误:

“ man”类错误地实现了“ Person”类。你是说要 扩展“人”并继承其成员作为子类?属性 “ man”类型中缺少“ walk”,但在“ Person”类型中必需。(2720)

答案 3 :(得分:3)

来自@ nitzan-tomer的精彩回答!帮了我很多...我用他的演示扩展了一下:

IPoint interface;
Point implements IPoint;
Point3D extends Point;

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

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

Hier extended demo

答案 4 :(得分:1)

  1. 界面扩展了形状的界面
  2. 接口可扩展类的形状
  3. 类实现接口应实现该接口提供的所有字段
  4. Class实现具有形状的类
  5. Class扩展了所有字段的类

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