【问题标题】:Possible to create an abstract property?可以创建抽象属性吗?
【发布时间】:2021-02-22 06:43:34
【问题描述】:

我在 Child 类中有一个如下所示的属性:

formModel = {
    motive: 0,
    coop: 0,
    leadership: 0,
    teamwork: 0,
    community: 0,
    professional: 0,
    role_model: 0,
    supportive: 0,
    problem_solving: 0
};

但在其他子类中,这个属性是不同的。

formModel = {
    motive: 0,
    coop: 0,
    leadership: 0,
    teamwork: 0,
    community: 0,
    professional: 0,
    communication: 0,
    respect: 0,
    morale: 0,
    role_model: 0,
    supp_enviro: 0
};

属性的顺序改变了,名字也改变了。

我想在其 Parent 类中声明此属性的 abstract 版本。这可能吗?我在父级中使用public abstract formModel: Object; 没有这样的运气。

编辑:

这是我得到的错误:

vendor.bundle.js:40839 Uncaught Error: Unexpected value 'undefined' declared by the module 'AppModule'
    at syntaxError (vendor.bundle.js:40839)
    at vendor.bundle.js:54719
    at Array.forEach (<anonymous>)
    at CompileMetadataResolver.webpackJsonp.../../../compiler/@angular/compiler.es5.js.CompileMetadataResolver.getNgModuleMetadata (vendor.bundle.js:54717)
    at JitCompiler.webpackJsonp.../../../compiler/@angular/compiler.es5.js.JitCompiler._loadModules (vendor.bundle.js:66103)
    at JitCompiler.webpackJsonp.../../../compiler/@angular/compiler.es5.js.JitCompiler._compileModuleAndComponents (vendor.bundle.js:66076)
    at JitCompiler.webpackJsonp.../../../compiler/@angular/compiler.es5.js.JitCompiler.compileModuleAsync (vendor.bundle.js:66005)
    at PlatformRef_.webpackJsonp.../../../core/@angular/core.es5.js.PlatformRef_._bootstrapModuleWithZone (vendor.bundle.js:71695)
    at PlatformRef_.webpackJsonp.../../../core/@angular/core.es5.js.PlatformRef_.bootstrapModule (vendor.bundle.js:71681)
    at Object.../../../../../src/main.ts (main.bundle.js:1339)

我注意到,如果我将以下方法添加到我的父类而不是子类,我只会收到此错误:

public handleRadioButtonChanges(event: Event): void {
    console.log("test");
}

【问题讨论】:

  • “没有这样的运气”是什么意思?父类是抽象的吗?
  • 在父类中,我输入了public abstract formModel: Object;,但出现错误。它似乎不像那样工作。
  • 父类是否为abstract?你能发布一些错误的代码吗?
  • 父类是abstract,是的。相关代码我已经贴出来了。
  • 很抱歉,您还没有发布enough code 来重现您的问题。我可以使用您提到的抽象属性创建一个抽象父类,并且没有错误。你得到什么错误,你从哪里得到它们?

标签: angular typescript


【解决方案1】:

上述问题的答案肯定是是的,您可以创建抽象属性。我可以毫无错误地执行以下操作:

// what are the restrictions on FormModel? 
// See [@amal's answer](https://stackoverflow.com/a/46328720/2887218) 
// for discussion about this
interface FormModel {
  [key: string]: number;
}

abstract class Parent {
  public abstract formModel: FormModel;  
  public handleRadioButtonChanges(event: Event): void {
    console.log("test");
}
}

class Child extends Parent {
  formModel = {
    motive: 0,
    coop: 0,
    leadership: 0,
    teamwork: 0,
    community: 0,
    professional: 0,
    role_model: 0,
    supportive: 0,
    problem_solving: 0
  };
}

class AnotherChild extends Parent {
  formModel = {
    motive: 0,
    coop: 0,
    leadership: 0,
    teamwork: 0,
    community: 0,
    professional: 0,
    communication: 0,
    respect: 0,
    morale: 0,
    role_model: 0,
    supp_enviro: 0
  };
}

但是,您遇到的错误似乎是 webpack 特有的,我不知道是什么原因造成的。当我使用 tsc 编译时,使用或不使用 public abstract formModel: FormModel; 行发出的 JavaScript 没有区别。它只是类型信息,往往无法进入 JavaScript。您可能需要提供有关您的环境的更多信息,以便有人可以复制。

无论如何,您遇到的问题可能与抽象属性本身几乎没有关系,除了当您将该属性添加到父类时它会被暴露。也许this GitHub issue 是相关的?还是this SO question?我真的不知道,因为我没有任何 webpack 专业知识。

【讨论】:

  • 只是指出,这个基本上传达了我在回答中提到的使用接口定义类型的相同想法。如果在这种类型的所有实例中“需要”已知属性,则定义已知属性,如果不使用动态键!比如[key: string]: number;[key: string]: any;(如果你不确定number的类型)
  • 啊。我现在意识到问题可能出在我放置某个功能的位置。不过你是对的;这个问题与抽象属性无关。
  • @amal 当然,我确实提到了FormModel 的类型定义,但这既不是问题的重点(如果抽象属性是可能的......答案:是的),也不是实际的@Nxt3 遇到的问题(这与 webpack 或 TypeScript 和 webpack 之间的相互作用有关)。编辑:现在在我的帖子中提到你的答案,如果有帮助的话:-)
【解决方案2】:

如果你只关心它的类型,你可以为它定义一个接口。

export interface FormModel {
 motive: number;
 coop: number;
 leadership: number;
 teamwork: number;
 community: number;
 professional: number;
 role_model: number;
 supportive: number;
 problem_solving: number;
}

然后在 child 中,您可以简单地声明这个 formModel 类型为在 parent 中定义的 FormModel(您还必须在 child component.ts 文件中导入此接口)。

import { FormModel } from 'app/<Interface's location>';

formModel: FormModel;

编辑

如果有帮助,您可以通过将 ? 添加到其声明中(如 motive?: number;)使它们成为可选项。因此,将此添加到您认为是可选的属性中。或者只是简单地声明你认为总是存在的属性(没有可选的),然后像这样添加一个动态属性。

export interface FormModel {
 motive: number;
 coop: number;
 leadership: number;
 teamwork: number;
 community: number;
 professional: number;
 role_model: number;
 supportive: number;
 problem_solving: number;
 [key: string]: any; // <-- leaving room for optional extra properties
}

【讨论】:

  • 唯一的问题是formModel属性的属性数量不同。我想让它在父类中通用,以便我可以将更多逻辑移入其中,而不是在组件中处理它。
  • 如果有帮助,您可以通过将 ? 添加到其声明中(如 motive?: number;)使它们成为可选。查看我的更新答案
  • 关于您的更新,属性的顺序无关紧要。但名字确实很重要。那么,当您在父类中定义该对象formModel 及其属性时,您“肯定”知道什么?如果你有一个属性列表,你确定它会在每个实例化中都有,那么我们可以从它开始。至少,您应该对这个对象有所了解,这使您在父对象中将其定义为某种类型。如果您一开始对它一无所知,我们可以简单地用动态键声明它。请先澄清这一点?
  • 我没有意识到名字很重要。这解决了我的问题。谢谢!
  • 没有解决吗?您还有其他问题吗?
猜你喜欢
  • 2022-01-15
  • 2013-04-03
  • 1970-01-01
  • 1970-01-01
  • 2012-10-11
  • 1970-01-01
  • 1970-01-01
  • 2012-01-01
  • 2018-09-16
相关资源
最近更新 更多