我对扩展抽象类的所有子类使用依赖注入。
在抽象构造函数类中,如果需要,我会在其子节点中启动我计划覆盖的方法。
我遇到的问题是我的注入依赖项在从super。
启动的override类中不可见以下是代码示例:
abstract class Base {
constructor(view: string) {
this._assemble();
}
protected _assemble(): void {
console.log("abstract assembling for all base classes");
}
}
class Example extends Base {
constructor(view: string, private helper: Function) {
super(view);
console.log(this.helper);
}
public tryMe(): void {
this._assemble();
}
protected _assemble(): void {
super._assemble();
// at first run this.helper will be undefined!
console.log("example assembling", this.helper);
}
}
let e = new Example("hoho", function () { return; })
console.log("So now i will try to reassemble...");
e.tryMe();
因此,问题的核心是typescript将Example类转换为代码,如下所示:
function Example(view, helper) {
_super.call(this, view);
this.helper = helper;
console.log(this.helper);
}
而不是:
function Example(view, helper) {
this.helper = helper;
_super.call(this, view);
console.log(this.helper);
}
如您所见,如果我在this.helper
之前将_super
放在JavaScript中,this.helper
将始终显示在_assemble
中。即使super
会调用_assemble
函数。
但默认情况下,在_super
电话之后进行分配。因此,如果super
类将调用汇编。在第一次示例中,它在覆盖_assemble
方法中不可见。
所以我的问题是......
或
现在我修复了我的问题,只是从_assemble
类删除super
,并始终从子进程中调用它。但这只是错了。
Nota Bene: 这是编译的JavaScript代码与固定的JavaScript代码演示:
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var Base = (function () {
function Base(view) {
this._assemble();
}
Base.prototype._assemble = function () {
document.write("<p>abstract assembling for all base classes</p>");
};
return Base;
}());
var Example = (function (_super) {
__extends(Example, _super);
function Example(view, helper) {
_super.call(this, view);
this.helper = helper;
console.log(this.helper);
}
Example.prototype.tryMe = function () {
this._assemble();
};
Example.prototype._assemble = function () {
_super.prototype._assemble.call(this);
// at first run this.helper will be undefined!
document.write("<p>example assembling <b/>" + (this.helper) + "</b></p>");
};
return Example;
}(Base));
var e = new Example("test", function () { return "needle"; });
document.write("<p><i>So now i will try to reassemble...</i></p>");
e.tryMe();
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var Base = (function () {
function Base(view) {
this._assemble();
}
Base.prototype._assemble = function () {
document.write("<p>abstract assembling for all base classes</p>");
};
return Base;
}());
var Example = (function (_super) {
__extends(Example, _super);
function Example(view, helper) {
/**
* Slight change, compiled assigning to this BEFORE _super.
*/
this.helper = helper;
_super.call(this, view);
console.log(this.helper);
}
Example.prototype.tryMe = function () {
this._assemble();
};
Example.prototype._assemble = function () {
_super.prototype._assemble.call(this);
// at first run this.helper will be undefined!
document.write("<p>example assembling <b/>" + (this.helper) + "</b></p>");
};
return Example;
}(Base));
var e = new Example("test", function () { return "Needle"; });
document.write("<p><i>So now i will try to reassemble...</i></p>");
e.tryMe();
答案 0 :(得分:5)
在Java和其他OOP语言中,必须在实例化当前对象之前将super()称为。
这是合乎逻辑的,因为child cannot be born before parent
。
TypeScript 2 now can have statements before super
, if they are not using to this
.
这是为什么this
在晚餐前不能使用的答案的一部分。
问题触摸的下一部分是,parent
对象实际上在其子项assemble
中实际调用了覆盖,而该子对象根本没有被实例化。
这看起来很奇怪,因为没有实例化子项,但是父构造函数调用了子方法......并且看起来不自然,就像未出生的孩子说“爸爸”一样。
See similar post about this issue.
但这是一种错误的思考方式。来自将在构造函数中使用的子项的覆盖,纯粹存在以更改子项的实例化方式。
在父构造函数中使用的方法覆盖必须告诉您应该如何制作实例。从那些可用于父级的资源,而不是来自您的不存在的实例所拥有的资源。< / p>
原型中的继承通常通过合成具有extend
功能的新原型来实现。
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
从这个角度看,没有“孩子”和“父母”这样,但有“套”,有点。只有在已存在的情况下,Set才能通过另一个集合进行扩展。这将我们带到:
Top-down and bottom-up design.
原型和鸭子打字工作采用自下而上的设计。 OOP采用自顶向下设计。
就是不要!通过学习和实施,利用OOP思想的力量!在这里如何成功:
Use static,但请注意,此更改对于您的对象的所有实例都是相同的。
如果你只将它用于依赖注入,这是可以的
智能覆盖。
不要使用来自兄弟(“child”)实例的额外资源,并创建一个将从构造函数中调用的额外方法。
下面的示例(请注意,这不违反LSP,因为在构造函数中只设置了__assembled
一次):
abstract class Base {
constructor(view: string) {
this._assemble();
}
protected _assemble(): void {
console.log("abstract assembling for all base classes");
}
}
class Example extends Base {
private __assembled: boolean = false;
constructor(view: string, private helper: Function) {
super(view);
this._assemble_helper();
this.__assembled = true;
}
public tryMe(): void {
this._assemble();
}
protected _assemble(): void {
super._assemble();
// removed from here all extra resources
// but run them when u need to assemble them again.
if (this.__assembled) {
this._assemble_helper();
}
}
protected _assemble_helper(): void {
// at first run this.helper will be undefined!
console.log("example assembling", this.helper);
}
}
let e = new Example("hoho", function () { return; })
console.log("So now i will try to reassemble...");
e.tryMe();
以下是已编译的ES5结果:
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var Base = (function () {
function Base(view) {
this._assemble();
}
Base.prototype._assemble = function () {
console.log("abstract assembling for all base classes");
};
return Base;
}());
var Example = (function (_super) {
__extends(Example, _super);
function Example(view, helper) {
var _this = _super.call(this, view) || this;
_this.helper = helper;
_this.__assembled = false;
_this._assemble_helper();
_this.__assembled = true;
return _this;
}
Example.prototype.tryMe = function () {
this._assemble();
};
Example.prototype._assemble = function () {
_super.prototype._assemble.call(this);
// removed from here all extra resources
// but run them when u need to assemble them again.
if (this.__assembled) {
this._assemble_helper();
}
};
Example.prototype._assemble_helper = function () {
// at first run this.helper will be undefined!
console.log("example assembling", this.helper);
};
return Example;
}(Base));
var e = new Example("hoho", function () { return; });
console.log("So now i will try to reassemble...");
e.tryMe();