何时在 Angular 项目中使用类或接口? [关闭]

Posted

技术标签:

【中文标题】何时在 Angular 项目中使用类或接口? [关闭]【英文标题】:When to use Class or Interface in Angular project? [closed] 【发布时间】:2019-06-18 18:47:14 【问题描述】:

我今天来到这里是因为我有一个关于Angular 中的类和接口的问题,就像标题所说的那样。

从我的角度来看,我理解这一点:

接口在 Typescript 中用于执行类型检查,它们在这里直到转译然后消失在生产中。此外接口不能用于实例化

来自 ES6 的类也用于类型检查,但它们在转译后保留并生成代码 在生产中。此外,它们用于实例化。

所以,基本上,如果我们在生产中不需要它们,如果我们只需要类型检查,接口是有用的。 相反,如果我们在生产中需要 Class,特别是在实例化时,Class 就在这里。

我是正确的还是我错过了一些关于类和界面的东西?

【问题讨论】:

听起来不错。 more ES6 类与类型检查无关。 Typescript 类可能用于类型检查,也可能不用于类型检查,具体取决于它们是否是使用类型构造的。 Typescript 接口除了类型检查没有其他用途 Difference between interfaces and classes in Typescript的可能重复 这是***.com/questions/51716808/…和***.com/questions/40973074/…的副本 【参考方案1】:

你是对的。当您只需要类型检查时,接口很棒,而当您不仅需要类型检查,而且需要一些方法或需要一些其他逻辑时,类也很棒。

就个人而言,我总是从使用接口开始,一旦我需要一些方法,我会添加一个类并继承接口。我还要补充一点,我 无论您是否使用类,都希望总是有一个接口。这允许您传递/注入接口,而不必多次重新实例化类。

如果我需要一些方法(这意味着我需要class),我会遵循一个典型模式的示例

interface IPerson 
    firstName: string;
    lastName: string;
    age: number;
    getFullName(): string;

class Person implements IPerson 
    public firstName: string;
    public lastName: string;
    public age: number;
    constructor(firstName: string, lastName: string, age: number) 
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    
    getFullName(): string 
        return `$this.firstName $this.lastName`
    


const person: IPerson = new Person('John', 'Doe', 44);

我永远不会在任何地方注入或需要导入Person,除非我真的需要“结识”一个新人。我总是可以注入 IPerson 来代替,只要作为类传入的内容,接口将允许我调用所有类方法并根据需要访问属性。

但是,有时我不需要方法,但我需要一个数据契约(或者只是想阻止 TypeScript 被激怒,我没有告诉它一切是什么):

interface IPerson 
    firstName: string;
    lastName: string;
    age: number;


const person: IPerson = <IPerson>
    firstName: 'John',
    lastName: 'Doe',
    age: 44
;

这样做仍然可以为您提供一种方法来动态创建一个符合接口的变量。但是,当你这样做时没有任何方法(所以你会丢失你的 getFullName 函数并且必须手动运行它)

总的来说,我发现自己使用结构化 json 的 http 返回接口。我真的不需要在前端对他们做更多的事情,因为后端已经为我完成了繁重的工作。因此,为每个返回值创建一个类可能有点矫枉过正,但有些人更喜欢这样。

要提出的另一件事是,创建所有这些模型非常耗时。虽然它有回报。在我的一个项目中,我使用 npm 模块根据我的 c# 模型自动生成 TypeScript 接口。这节省了大量的打字时间,并认为这很酷 (https://www.npmjs.com/package/csharp-models-to-typescript)

另一种流行的解决方案是使用Swagger Codegen。你可以'swaggerize'你的后端并让swagger codegen为你生成你的模型和服务。它很光滑。 Here's an example repo 使用 Angular 和 C# 作为后端。

总的来说,这确实是您的偏好。请记住,如果您需要方法和额外的层来构建给定的模型,那么类是最好的。如果您只需要类型而不关心其他花哨的“语法糖”,只需使用接口。正如您所提到的,接口在生产中消失了,所以这当然是一个加分项。

https://jsfiddle.net/mswilson4040/3vznkbq0/7/

【讨论】:

为模型使用接口而不是类,并将所有逻辑保留在服务中不是更好吗?如果我们向模型添加方法,我们可能需要在某些时候将服务注入模型中以访问某些功能(例如检索翻译)。这意味着我们要么必须使模型本身可注入(这是我们永远不应该做的事情),要么将需要注入的方法移动到另一个服务中,从而将业务逻辑分散在模型/服务之间。 技术上你可以做到这一点。但是,在上述场景中,模型的“额外逻辑”不会 ping 服务器或发出任何 http 请求。 IMO 服务应保留用于服务器通信/全局功能(例如发射器或其他东西)。实际的数据契约(模型/接口)应该与服务隔离。该服务的工作应该严格来说是 http 请求,并且在确保从服务器 / http 请求返回的任何数据都被水合到您的模型中时,应该是“数据合同警察”。显然,有多种方法可以做到这一点 ... 但是,如果您真的想将您的模型包含在您的服务代码中和/或将您的服务注入您的模型代码中,您可以这样做。我会争辩说,在那一点上,您正在尝试设置一些类似 ORM 的轻量级设置,以便您可以执行类似 await Person.getUserProfile() 的操作,这很好,但不是我在前端设置的方式世界【参考方案2】:

由于您还在问题中标记了 Angular,我想从 Angular 的角度补充答案。

Angular 在通过 http 检索数据时也使用接口(或类)作为结构。

export interface Product 
  id: number;
  productName: string;
  productCode: string;
  tags?: string[];
  price: number;
  description: string;
  imageUrl: string;


@Injectable( providedIn: 'root' )
export class ProductService 
  private productsUrl = 'api/products';

  constructor(private http: HttpClient)  

  getProducts(): Observable<Product[]> 
    return this.http.get<Product[]>(this.productsUrl);
  

http.get 方法获取数据并填充提供的product 数组结构。这使得处理来自组件的数据更加更容易。

【讨论】:

我知道我迟到了,但为什么不上课呢?特别是如果您最终会提供与ProductProducts 的数组交互的方法,例如对数组中的字段求和等。还是应该在后端API 上完成大部分操作?我一直在纠结何时在 Angular 应用程序中使用类,因为大多数开发人员似乎认为接口是首选构造。 现在 Angular v12 默认具有严格的类型,一个类需要将 every 字段初始化为某个值。接口不需要这样。此外,当执行上述代码时,它不会为每个检索到的项目创建 Product 类的实例。而是将它们 shapes 放入类形状中。因此,如果您定义了方法,则必须先将返回的数据对象映射到 Product 类中创建的对象中才能调用它们。欲了解更多信息:***.com/questions/51763745/…

以上是关于何时在 Angular 项目中使用类或接口? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

我如何选择抽象类或接口..? [复制]

何时使用 Ngzone.run()?

何时在 Angular 中使用 transclude 'true' 和 transclude 'element'?

如何将 JSON 数据加载到 Angular 中的类或类数组中?

在 Angular 6 中的类上实现

Java中的异常处理:何时抛出异常,何时捕获异常?