我在挣扎。
当扩展一个类时,我可以很容易地向它添加一些新属性。
但是,当我扩展基类时,如果我想向基类的对象(简单对象的属性)添加新属性,该怎么办?
下面是一个带有一些代码的示例。
基类
type HumanOptions = {
alive: boolean
age: number
}
class Human {
id: string
options: HumanOptions
constructor() {
this.id = '_' + Math.random()
this.options = {
alive: true,
age: 25,
}
}
}
派生类
type WizardOptions = {
hat: string
} & HumanOptions
class Wizard extends Human{
manaLevel: number
options: WizardOptions // ! Property 'options' has no initializer and is not definitely assigned in the constructor.
constructor() {
super()
this.manaLevel = 100
this.options.hat = "pointy" // ! Property 'options' is used before being assigned.
}
}
现在,正如您可以从行内注释中看到的,这将激怒TypeScript。但这在JavaScript中工作。那么,实现这一目标的正确方法是什么呢?如果没有,问题是在我的代码模式本身吗?什么模式适合这个问题?
也许您想知道为什么我要在options
对象中使用这些属性。它可能非常有用!例如:只有选项
中的属性才能通过某些UI进行编辑。因此,其他一些代码可以在类中动态查找选项
,并在UI上公开/更新它们,同时像id
和manaLevel
这样的属性将被忽略。
笔记
我知道我可以为向导这样做:
class Wizard extends Human{
manaLevel: number
options: {
hat: string
alive: boolean
age: number
}
constructor() {
super()
this.manaLevel = 100
this.options = {
alive: true,
age: 25,
hat: "pointy"
}
}
}
但是代码不是很干燥,我必须手动管理选项继承(这在复杂的应用程序中是不理想的)。
这是部分答案,我会在你提供更多信息时更新。例如,上面你问题下的问题的答案。
第二个错误是您在Wizard
中声明的选项字段的结果。
这在Javascript中起作用,因为您依赖于原型继承,并且没有在向导
类中声明新的选项
字段(如果有的话,该类也会隐藏Human.options
)。
你可以用以下方法来做:操场
type HumanOptions = {
alive: boolean
age: number
}
class Human<Options extends HumanOptions> {
id: string
options: Options
constructor() {
this.id = '_' + Math.random()
this.options = {
alive: true,
age: 25,
} as Options
}
}
type WizardOptions = {
hat: string
} & HumanOptions
class Wizard extends Human<WizardOptions> {
manaLevel: number
constructor() {
super()
this.manaLevel = 100
this.options.hat = "pointy"
}
}
请注意,您完全负责设置选项
的所有必需道具。
如果您只是要重用超类中的属性,但将其视为更窄的类型,您可能应该在子类中使用声明
属性修饰符,而不是重新声明字段:
class Wizard extends Human {
manaLevel: number
declare options: WizardOptions; // <-- declare
constructor() {
super()
this.manaLevel = 100
this.options.hat = "pointy" // <-- no problem now
}
}
在这里使用declare
可以抑制该行的任何JavaScript输出。它所做的只是告诉TypeScript编译器,在向导
中,选项
属性将被视为向导选项
,而不仅仅是人类选项
。
公共类字段目前处于TC39过程的第3阶段,因此很可能是当前形式的JavaScript的一部分,或者与之相近。当这种情况发生时(或者现在如果你有一个足够新的JS引擎的话),你编写的代码最终会生成如下的JavaScript
class Wizard extends Human {
manaLevel;
options; // <-- this will be here in JavaScript
constructor() {
super();
this.manaLevel = 100;
this.options.hat = "pointy";
}
}
这只是没有类型注释的TypeScript。但是JavaScript中的options
声明将子类中的options
初始化为undefined
。因此,在分配之前使用此选项将是正确的:
console.log(new Wizard()); // runtime error!
// this.options is undefined
所以你从TypeScript得到的错误是一个很好的错误。
最初,TypeScript实现了类字段,因此如果不显式初始化字段,则仅声明字段不会产生效果。TypeScript团队认为类字段最终将在JavaScript中实现。但他们错了。如果您的编译器选项没有启用
--使用定义或类字段
(请注意,如果您将--目标
设置得足够新,它将自动包括在内;请参见microsoft/TypeScript#45653),那么它将输出JS代码,而您的示例不会出现运行时错误。
因此,您可以争辩说,如果您没有使用
--useDefeForClassFields
,编译器不应该给您一个错误。在--use定义ForClassFields
存在之前,这样的论点实际上是在微软/TypeScript#20911和微软/TypeScript#21175上提出的。
但是我认为TS团队不再太接受这个了。随着时间的推移,JavaScript中声明的类字段被初始化为未定义的将是常态,而不是例外,支持旧的不一致版本的类字段不是任何人的优先事项。请参阅microsoft/TypeScript#35831,其中的建议基本上是使用
声明
。这也是我在这里的建议。
操场连结至守则
我在下棋。我想做一个抽象的piece类,然后可以通过pawn/knight/rook/等进行扩展。假设我的piece类是这样的: 我希望Pawn具有相同的sayName功能,但我希望它具有不同的movePiece功能,因为Pawn有自己独特的移动方式。我怎么做典当,使它扩展件,并覆盖件的移动件功能?
本文向大家介绍TypeScript 基本继承,包括了TypeScript 基本继承的使用技巧和注意事项,需要的朋友参考一下 示例 本示例说明如何Car使用extends关键字创建该类的非常简单的子类。的SelfDrivingCar类重写move()方法和用途使用基类FPGA实现super。
问题内容: 是否有理由要声明类声明object? 我刚刚找到了执行此操作的代码,但找不到很好的理由。 问题答案: 是否有理由要声明类声明object? 在Python 3中,除了Python 2和3之间的兼容性之外,没有任何理由。在Python 2中,原因很多。 Python 2.x故事: 在Python 2.x(从2.2开始)中,有两种类型的类,取决于是否存在object作为基类的类: “经典”
问题内容: 我对使用python list对象感兴趣,但功能略有改变。特别是,我希望列表是1索引而不是0索引。例如: 输出应为:1 但是,当我更改和方法来执行此操作时,出现了错误。我对这些方法进行了很多修改,但这基本上就是我在那里做的: 我想问题是它本身正在调用与定义的方法相同的方法。如果是这样,如何使它使用方法而不是方法?我尝试使用代替,但导致投诉 有任何想法吗?另外,如果您可以为此指出一个好的
我目前正在尝试使用JaxB,但对于一个相对简单的示例,我并不是很成功。我的示例如下: 我所有的尝试(甚至编组)都失败了。我浏览了BlaiseDoughan的博客,包括http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-xsitype.html但他们似乎对我的例子都没有帮助。我很可能误用了他的例子。在我看来,我的示例应该是JaxB中
FAQs in section [22]: [22.1] 将接口和实现分离的作用是什么? [22.2] 在C++中如何分离接口和实现(就象 Modula-2)? [22.3] 什么是 ABC? [22.4] 什么是“纯虚”成员函数? [22.5] 如何为包含指向(抽象)基类的指针的类定义拷贝构造函数或赋值操作符? 22.1 将接口和实现分离的作用是什么? 接口是公司最有价值的资源。设计接口比用一堆