简体   繁体   English

Typescript 中接口和类的区别

[英]Difference between interfaces and classes in Typescript

What is the different between Typescript Interfaces and Classes? Typescript 接口和类之间有什么区别? When do I use a Class?我什么时候使用类? When do I use Interfaces?我什么时候使用接口? What are the advantages of them?它们的优点是什么?

I need to create some kind of types for an http-request to my backend server (Doing it with Angular 2), like : },我需要为后端服务器的 http 请求创建某种类型(使用 Angular 2 进行),例如:},

"fields": {
  "project": {
      "id": "10000"
  },
  "summary": "something's wrong",
  "issuetype": {
      "id": "10000"
  },
  "assignee": {             // not neccesary required
      "name": "homer"
  },
  "reporter": {
      "name": "smithers"
  },
  "priority": {            // not neccesary required
      "id": "20000"
  }
}

What should I use for building these models?我应该使用什么来构建这些模型? Thank you!谢谢!

2019: Update on Differences and Usages 2019 年:差异和用法更新

First, there is the obvious difference: syntax .首先,有一个明显的区别:语法 This is a simple, but necessary to understand difference: Interface properties can end in commas or semi-colons, however class properties can only end in semi-colons.这是一个简单但必须理解的区别:接口属性可以以逗号或分号结尾,但是类属性只能以分号结尾。 Now the interesting stuff.现在是有趣的东西。 The sections about when to use and not to use may be subjective - these are the guidelines I give people on my team, but it is possible that other teams will have other guidelines for valid reasons.关于何时使用和不使用的部分可能是主观的——这些是我给我团队中的人的指导方针,但其他团队可能会出于正当理由制定其他指导方针。 Feel free to comment if your team does it differently, I would love to learn why.如果您的团队有不同的做法,请随时发表评论,我很想知道原因。

Interfaces : Allow for defining a type that will be used during design and compile time for strong typing.接口:允许定义将在设计和编译期间用于强类型的类型。 They can be "implemented" or "extended" but cannot be instantiated (you can't new them).它们可以被“实现”或“扩展”,但不能被实例化(你不能new它们)。 They get removed when transpiling down to JS so they take up no space, but they also cannot be type checked during runtime, so you can't check if a variable implements a specific type at runtime (eg foo instanceof bar ), except by checking the properties it has: Interface type check with Typescript .它们在转译为 JS 时被删除,因此它们不占用空间,但它们也不能在运行时进行类型检查,因此您无法在运行时检查变量是否实现了特定类型(例如foo instanceof bar ),除非通过检查它具有的属性: 使用 Typescript 检查接口类型

When to use interfaces : Use them when you need to create a contract of the properties and functions for an object that will be used in more than one place in your code, especially more than one file or function.何时使用接口:当您需要为一个对象创建属性和函数的契约时使用它们,该对象将在代码中的多个位置使用,尤其是多个文件或函数。 Also, use when you want other objects to start with this base set of properties, such as having a Vehicle interface that multiple classes implement as specific types of vehicles, like Car , Truck , Boat (eg class Car implements Vehicle ).此外,当您希望其他对象以该基本属性集开始时使用,例如具有多个类实现为特定类型车辆的Vehicle接口,如CarTruckBoat (例如class Car implements Vehicle )。

When not to use interfaces : When you want to have default values, implementations, constructors, or functions (not just signatures).何时不使用接口:当您想要拥有默认值、实现、构造函数或函数(不仅仅是签名)时。

Classes : Also allow for defining a type that will be used during design and compile time for strong typing, and, additional, can be used during runtime.:还允许定义将在设计和编译期间用于强类型的类型,此外,还可以在运行时使用。 This also means that the code is not compiled out, so it will take up space.这也意味着代码没有编译出来,所以会占用空间。 This is one key difference mentioned by @Sakuto, but has more implications than just space.这是@Sakuto 提到的一个主要区别,但其含义不仅仅是空间。 It means that classes can be typed checked, retaining the understanding of "who they are" even in the transpiled JS code.这意味着可以检查类的类型,即使在转译的 JS 代码中也能保留对“它们是谁”的理解。 Further differences include: classes can be instantiated using new and can be extended, but not implemented.进一步的区别包括:类可以使用new实例化,可以扩展,但不能实现。 Classes can have constructors and actual function code along with default values.类可以具有构造函数和实际函数代码以及默认值。

When to use classes : When you want to create objects that have actual function code in them, have a constructor for initialization, and/or you want to create instances of them with new .何时使用类:当您想创建包含实际功能代码的对象时,有一个用于初始化的构造函数,和/或您想用new创建它们的实例。 Also, for simple data objects, you can use classes for setting up default values.此外,对于简单的数据对象,您可以使用类来设置默认值。 Another time you would want to use them is when you are doing type checking, though there are workarounds for interfaces if needed (see the interface section OS link).另一个你想使用它们的时候是在你做类型检查时,尽管如果需要,有接口的解决方法(请参阅接口部分 OS 链接)。

When not to use classes : When you have a simple data interface, do not need to instantiate it, when you want to have it implemented by other objects, when you want to simply put an interface on an existing object (think type definition files) or when the space it would take up is prohibitive or unwarranted.何时不使用类:当您有一个简单的数据接口时,不需要实例化它时,当您希望它由其他对象实现时,当您只想将接口放在现有对象上时(想想类型定义文件)或者当它占用的空间令人望而却步或没有根据时。 As a side note, if you look in .d.ts files you will notice that they only use interfaces and types, and thus this is completely removed when transpiled to TS.作为旁注,如果您查看 .d.ts 文件,您会注意到它们仅使用接口和类型,因此在转换为 TS 时将完全删除。

Final note , there are two other options than just classes and interfaces, the first is something called a "type", which is pretty similar to an interface, but check this SO post, specifically the 2019 Update answer: Typescript: Interfaces vs Types .最后要注意的是,除了类和接口之外,还有其他两个选项,第一个是称为“类型”的东西,它与接口非常相似,但请查看此 SO 帖子,特别是 2019 年更新答案: Typescript: Interfaces vs Types The last option is to go functional programming style (not OOP) with TS.最后一个选择是使用 TS 使用函数式编程风格(而不是 OOP)。

For the full story with examples visit PassionForDev.com and more good reading on classes vs. inheritance with examples visit https://jameshenry.blog/typescript-classes-vs-interfaces/ .有关示例的完整故事,请访问PassionForDev.com以及更多关于类与继承的优秀阅读示例,请访问https://jameshenry.blog/typescript-classes-vs-interfaces/

According to Angular 2 styleguide it's recommended to use Class over Interface for the typing.根据Angular 2 样式指南,建议使用Class over Interface进行输入。 The main difference is that class will persist when compiled while Interface are purely removed since they do not serve any usage.主要区别在于class将在编译时持久存在,而Interface则被完全删除,因为它们没有任何用途。

Just stay consistent over the whole project, and prefer the styleguide approach with class , who know, maybe one day you will need to add method to your models .只要在整个项目中保持一致,并且更喜欢使用class的 styleguide 方法,谁知道呢,也许有一天你需要为你的models添加method

Check answer below for more details: https://stackoverflow.com/a/55505227/5463904查看下面的答案以获取更多详细信息: https : //stackoverflow.com/a/55505227/5463904

Simply Class is to create objects and Interface assists you what these objects should contain.简单的类是创建对象,接口帮助你这些对象应该包含什么。

Class is like a blueprint/template using which we can create objects.类就像一个蓝图/模板,我们可以使用它来创建对象。 Interface is like a contract on which a Class has to agree on to implement that Interface or define what this blueprint should contain.接口就像一个契约,类必须在该契约上达成一致以实现该接口或定义此蓝图应包含的内容。

A simple class:一个简单的类:

class Car {
    engine: string; // 'var' is not used;

    constructor(engine: string) { // This is how we create constructor
        this.engine = engine;
    }

    display(): void { // 'function' keyword is not used here.
        console.log(`Engine is ${this.engine}`); // just a log.
    }
}

var objCar = new Car('V8'); // creates new onject
objCar.display(); // output: Engine is V8
console.log(objCar.engine); // output: V8 (accessing member here)

A simple Interface:一个简单的界面:

    interface IPerson { // This is how we create an interface.
        firstName: string, // use commas to separate.
        lastName: string, // In classes we use semi-colon to separate.
        displayDetails: (number) => string
    }

    // We are going to store 'interface object' in a variable.
    // i.e. we are implementing interface with variable(not class!!)
    var customer: IPerson = {

        firstName: 'jose jithin', // 'implements' variables
        lastName: 'stanly',

        // Now method implementation.
        // Note: the syntax of 'displayDetails' maybe a bit confusing (given below)
        // as two colons are used.
        // It specifies a return type(string) here for this method. 
        displayDetails: (rank): string => { return `This person has rank ${rank}. ` }  

        // It can be rewritten as following too.
        displayDetails: (rank) => { return `This person has rank ${rank}. ` };
        // i.e. return type need not be specified, just like a normal method definition syntax.
    }

    console.log(customer.firstName); // output: jose jithin

    console.log(customer.lastName);  // output: stanly

    console.log(customer.displayDetails(1)); // output: This person has rank 

I have detailed on Class and Interface with my article .我在我的文章中详细介绍了类和接口。 This might help you to understand.这可能有助于您理解。

Use typescript for making a Data model instead of class as compiler will not generate any corresponding JavaScript code for an interface at run time.使用 typescript 来创建数据模型而不是类,因为编译器不会在运行时为接口生成任何相应的 JavaScript 代码。 Whereas if you use a class for merely making a data model then compiler will create corresponding JS code for it hence will consume memory.而如果您使用一个类仅用于创建数据模型,那么编译器将为它创建相应的 JS 代码,因此会消耗内存。

A snippet from Angular's style guide: https://angular.io/guide/styleguide#interfaces来自 Angular 风格指南的片段: https : //angular.io/guide/styleguide#interfaces

"Consider using a class instead of an interface for services and declarables (components, directives, and pipes)." “考虑对服务和可声明对象(组件、指令和管道)使用类而不是接口。”

" Consider using an interface for data models. " 考虑使用数据模型的接口。

Interfaces接口

  • Describe how an object should look描述对象的外观
  • Exists compile time only, with the sole purpose of type checking仅存在编译时,仅用于类型检查

Classes班级

  • Used as a blueprint from which to instantiate/produce objects用作实例化/生成对象的蓝图
  • Can implement an interface which means it has to implement at least all of the properties/methods from the interface可以实现一个接口,这意味着它必须至少实现接口中的所有属性/方法

Example:例子:

interface Person {
    name: string;
    id: number;
    doStuff: () => void;
}

// implements Person says: You have to at least implement these things
// which are located on the person interface 
class employee implements Person {
    constructor(public name: string, public id: number){}

    doStuff () {console.log('Doing stuff')}
}

// interfaces can also describe variables and parameters
const p1: Person = {
    name: 'foo',
    id: 34,
    doStuff () {console.log('Doing stuff')}
}

我在过去 2 年中使用 angular,简单地说,当我想向对象添加任何行为时,我在任何类中使用类,例如,我想添加返回处理数据的 get 方法,并且当没有行为添加到对象时,我想直接访问对象,我将使用接口。如果你定义构造函数,你会限制用户在构造任何对象之前定义某些变量来初始化。

我发现当使用class es 而不是interface s 时,类型安全性没有那么强,特别是在 React 中作为 prop 传递的函数签名。

So there are multiple differences in class and interface.所以在类和接口上有很多不同。

Few of those are :其中很少有:

Definition定义
TypeScript Class is a template which holds methods,variables and provides a skeleton to object. TypeScript 类是一个模板,它包含方法、变量并为对象提供骨架。 TypeScript Interface is a blueprint which will tell a deriving class what to implement. TypeScript 接口是一个蓝图,它将告诉派生类要实现什么。

Practical Usage实际使用

Class : To design a skeleton of modules functionality wise类:明智地设计模块功能的骨架
interface : To hide a complexity from external accessing resource and securing core logic接口:隐藏外部访问资源的复杂性并保护核心逻辑

Instantiable可实例化

Class: We can Instantiate class using its object类:我们可以使用它的对象实例化类
Interface: We can not instantiate interface接口:我们不能实例化接口

you can find more difference at : https://codetopology.com/scripts/typescript/typescript-interface-vs-class/您可以在以下位置找到更多区别: https : //codetopology.com/scripts/typescript/typescript-interface-vs-class/

Interfaces in TypeScript serve two purposes: TypeScript 中的接口有两个目的:

  1. Blueprint for classes (eg, class Foo implements IFoo )类的蓝图(例如, class Foo implements IFoo
  2. “Typed Objects” (eg, let foo: IFoo = { … } ) “类型化对象”(例如, let foo: IFoo = { … }

#1 is the “classic” purpose, seen in Java, C#, et al.: an interface just describes what a class should look like. #1 是在 Java、C# 等中看到的“经典”目的:接口只是描述类应该是什么样子。 It isn't directly instantiated or anything.它没有直接实例化或任何东西。

#2 is something I, at least, have only seen in TypeScript: it's basically a compile-time-checked dictionary. #2 是我至少在 TypeScript 中见过的东西:它基本上是一个编译时检查的字典。

My experience has been that #2 leads to maintenance problems: that simple dictionary you create today may eventually have use for methods, in which case you have to alter all the callers, which enlarges testing scope.我的经验是#2 会导致维护问题:您今天创建的那个简单的字典最终可能会用于方法,在这种情况下,您必须更改所有调用者,这会扩大测试范围。

I RECOMMEND: Avoid pattern #2 for things public in favour of classes.我建议:避免使用模式 2 来支持类的公共事物。 It's fine as an internal compile-time check, but you'll advantage your code's future maintainers by facilitating addition of methods.作为内部编译时检查很好,但是通过促进方法的添加,您将有利于代码的未来维护者。 You may never need the methods, sure, but when you do you'll be glad you left yourself the option.您可能永远不需要这些方法,当然,但是当您这样做时,您会很高兴自己为自己留下了选择。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM