抽象クラスを拡張するすべての子クラスに依存性注入を使用します。
抽象コンストラクタークラスで、必要に応じて子でオーバーライドする予定のメソッドを起動するという問題。
スーパーから起動されたオーバーライドクラスに、注入された依存関係が表示されないという問題が発生しました。
コードの例を次に示します。
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();
Javaおよびその他のOOP言語では、現在のオブジェクトをインスタンス化する前にsuper()を呼び出す必要があります。
これは論理的ですchild cannot be born before parent
。なぜなら。
TypeScript 2super
は、を使用していない場合、の前にステートメントを含めることができるようになりましたthis
。
これは、this
夕食前に使用できない理由の一部でした。
質問が触れる次の部分は、この子がまったくインスタンス化されていないときに、parent
オブジェクトが実際にその子によるオーバーライドを呼び出すことassemble
です。
子がインスタンス化されていないため、奇妙に思えますが、親コンストラクターがchildrenメソッドを呼び出します...そして、胎児が「お父さん」と言うように不自然に見えます。
しかし、これはこのように考えるのは間違った方法です。コンストラクターで使用される子からのオーバーライドは、子がインスタンス化される方法を変更するために純粋に存在します。
親コンストラクターで使用されるメソッドオーバーライドは、インスタンスの作成方法を指示する必要があります。親が利用できるが、存在しないインスタンスが持っているリソースからは利用できないリソースから。
プロトタイプの継承は通常、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 __());
};
この観点からすると、「子供」や「親」というものはありませんが、「セット」というものはあります。セットは、それがすでに存在する場合にのみ、別のセットによって拡張できます。これにより、次のことが可能になります。
プロトタイプとダックタイピングはボトムアップ設計で機能します。トップダウン設計のOOP。
しないでください!それらを学び、実装することにより、OOPアイデアの力を活用してください!ここで成功する方法:
staticを使用しますが、この変更はオブジェクトのすべてのインスタンスで同じになることに注意してください。
これを依存性注入にのみ使用する場合は問題ありません
スマートオーバーライド。
兄弟(「子」)インスタンスからの追加のリソースを使用せず、コンストラクターから呼び出される独自の追加のメソッドを作成します。
以下の例(__assembled
コンストラクターで一度だけ設定されるため、これはLSPに違反しないことに注意してください):
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();
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加