我正在努力用Typescript解决我的抽象类问题。首先,让我知道我想要实现的目标。
我有一个名为Sword
的类,它扩展了Weapon
。每个Weapon
必须具有一些属性,例如damage
,但由于每个项目都有不同的伤害类型(例如,剑可能造成1点伤害,弓箭可能造成2点伤害)我必须在Sword
课程。abstract class Weapon
{
protected abstract damage: number;
constructor() {
alert(this.damage);
}
showDamage() {
alert(this.damage);
}
}
class Sword extends Weapon implements WeaponInterface {
protected damage: number = 999;
constructor() {
super();
}
}
const sword = new Sword;
sword.showDamage();
。我的脚本看起来像这样:
http://www.typescriptlang.org/play/
在undefined
999
运行上面的脚本,我收到两条消息:
Weapon.constructor
我不确定为什么Weapon.constructor
首先运行,因为只要super(this.damage)
先运行,就没有必要声明一个抽象值。例如,我必须执行Weapon
之类的操作才能将其传递到protected abstract damage
类。如果我这样做,我将不需要Typescript
。
如果我甚至无法用new Weapon(new Sword)
创建一个非常基本的继承,为什么它甚至支持抽象类呢?我必须SwordInterface
这意味着我无法在Inventory
等其他类上输入提示class Inventory
{
// Let's assume we have a "Shield" equipped so we can only equip "Sword" type
addSword(sword: SwordInterface): void {
}
}
。
super()
我对编译语言和Typescript不是很熟悉。谁能告诉我实现这个目标的正确方法是什么?将类属性传递给@echo off
setlocal EnableDelayedExpansion
set "order=RSSI RSRP RSRQ SINR "Tx Power" PCI"
rem Extract the "order" string into individual numerated elements
set "i=0"
for %%a in (%order%) do (
set /A i+=1
set "order[%%~a]=!i!"
)
rem Process the files and create an array with the desired order
set "lastFloor=0"
for /F "tokens=1-5 delims=_" %%a in ('dir /A:-D /B *.jpg') do (
set "name[%%b][!order[%%d]!]=%%a_%%b_%%c_%%d_%%e"
if %%b gtr !lastFloor! set "lastFloor=%%b"
)
rem Process the array elements
for /L %%i in (1,1,%lastFloor%) do (
for /F "tokens=2 delims==" %%a in ('set name[%%i]') do echo %%a
)
调用声音蹩脚......
我也不想破坏我的继承和接口。
答案 0 :(得分:3)
Typescript不会以任何特殊的方式处理类体中的属性初始化 - 它是作为该类构造函数的一部分完成的。可以想象一种将应用此作业的语言
class Sword extends Weapon implements WeaponInterface {
protected damage: number = 999;
很早,在任何构造函数运行之前。打字稿不这样做可能是因为它不是最简单和最一致的事情。
所以你必须自己做。实现所需的一种方法是将构造函数中的代码分成两部分,一部分用于初始化变量,另一部分用于完成其余部分。然后,您可以在调用每个部件时自行管理。这种技术有时称为two-phase initialization:
abstract class Weapon
{
protected abstract damage: number;
// NOTE: abstract properties must be initialized by subclasses
// in initialize() because they are used here in Weapon class constructor
protected initialize(): void { }
constructor() {
this.initialize();
alert(this.damage);
}
showDamage() {
alert(this.damage);
}
}
class Sword extends Weapon {
protected damage: number;
protected initialize(): void {
super.initialize();
this.damage = 999;
}
constructor() {
super();
}
}
const sword = new Sword;
sword.showDamage(); // shows 999 twice
答案 1 :(得分:1)
当然,基类构造函数首先运行。替代方案是什么?
class Base {
damage = 12;
}
class Derived extends Base {
constructor() {
// This should print 'undefined' ?
console.log(this.damage);
}
}
答案 2 :(得分:1)
基础c'tor在分配damage
之前运行。看一下Sword
生成的构造函数:
function Sword() {
var _this = _super.call(this) || this;
_this.damage = 999;
return _this;
}
作为替代方案,你可以将伤害作为基础c'tor参数传递:
abstract class Weapon {
protected damage: number;
constructor(damage: number) {
this.damage = damage;
alert(this.damage);
}
showDamage() { /*...*/ }
}
class Sword extends Weapon {
constructor() {
super(999);
}
}
或更短:
abstract class Weapon {
constructor(protected damage: number) {
alert(this.damage);
}
showDamage() { /* ... */ }
}