同じクラスのオブジェクトを作成します:Javascriptのプロトタイプ、プライベートメンバー、継承
-
21-09-2019 - |
質問
いくつかのコードでは、以上の千の言葉を言うことがあります:
/**
* Represents an amount of a resource
* @param {number} amount
* @param {string} type
*/
function Resource(amount, type)
{
var nAmount = amount;
var sType = type;
if (amount < 0)
{
throw new IllegalArgumentException("amount has to be positive");
}
/**
* @method Resource
* @return {number} amount of the resource
*/
this.getAmount = function()
{
return nAmount;
};
/**
* @method Resource
* @return {string} resource type
*/
this.getType = function()
{
return sType;
};
}
/**
* Addition of two resources produces a new resource with the sum amount
* the new object uses the old one as prototype
* @param {Resource} resource
* @return {Resource} new Resource object
*/
Resource.prototype.plus = function(resource)
{
if (!(resource instanceof Resource && this.getType() == resource.getType()))
{
throw new IllegalArgumentException("resources don't match.");
}
var newRes = Object.create(this); // create a new object based on the current one
// execute the Resource constructor on it
Resource.call(newRes, this.getAmount() + resource.getAmount(), this.getType());
return newRes;
};
リソースオブジェクトは不変と考えValueObjectsです。彼らはまた、操作上の新しいオブジェクトを返します。今だけではなく、「新しいリソース(引数)」を呼び出すので返すように新しいオブジェクトを作成するために、私は古いオブジェクトに基づいて新しいものを作成しました。また、これは、継承を許可します。
私は(私は将来のある時点でそれらを継承したいだけの場合)すべての私ValueObjectsでこれを使用することを始めている通り、、私はもう少しこのことについて考え始めています。
JavaScriptは不変オブジェクトを許可していません。しかし、オブジェクトは直接法の上書きまたはそのコンストラクタを呼び出すことにより、脆弱です。私にできることすべては、これらの悪い習慣であることを決定することです。残念ながらECMAScript5「フリーズ」は私のパターンは、それに対応しているものの、まだここではないです。
今、私はこのコードの重複と一緒に不変オブジェクトのコンストラクタを呼び出して、この「悪いスタイル」を持っていることを、私は、この手順をカプセル化する新しい関数を作成すると思っています:
Object.recreate = function(proto, constructor, args)
{
var obj = Object.create(proto);
constructor.apply(obj, args);
return obj;
};
そしてそのます:
Resource.prototype.plus = function(resource)
{
// if ... {throw ...}
return Object.recreate(this, Resource,
[this.getAmount() + resource.getAmount(), this.getType()]);
};
たぶん、誰かがこの関数の名前のためのより良いアイデアを持っています。 「再作成は私が最初に考えが何だったかです。あなたはこのパターンについてどう思いますか?それはオーバー抽象化ですか?私は私が継承だろうと確信しているクラスのためにこれを保存するべきか?私は重要な何かを見逃していましたか?
編集:私はこの記事では、現在反映されていない重要な何かを言及するのを忘れ参照してください。 ValueObjectのは簡単Object.createでクローン化されます。彼らのプライベートメンバーは不変です。しかし、どのような変更プライベートメンバーは?セット()がクローンで呼び出された場合、それはクロージャ内のオリジナルのプロトタイプオブジェクトを設定します!私Object.recreateはクロージャを再現するように、この問題が解決されます。
だから、プライベート変数と継承のためのより良い方法はありますか?なぜ誰もがクラス作成のための砂糖を使用していますか?私はprototypalismについてたくさん読んで、私はまだそれのこつを持っていません。
解決
年後に戻ってこれに来て、私はそれから書いたコードは概念をミキシングにおける欠陥だったと言うことができます。 JavaScriptが実際に閉鎖によって、真のプライベート変数を提供することができます。 ValueObjectsはとにかく不変であるので、しかし、そのプライベートな状態を変更することはできません、それはそれを隠すために物事をovercomplicatesます。
また、独創的なObject.recreateは1つがそれを必要とする場合は、1つは、クラスごとにseperatedly宣言する必要があることを、オーバー抽象化する「ファクトリメソッド」の一種である。
相続上の組成を使用してください! クロックフォードは偉大なJavaScriptの洞察力を与える: https://crockford.com/javascript/prototypal.htmlする
他のヒント
私はコピーまたはクローンが良い名前だと思います。そのような汎用的な関数を作成するためのメカニズムを説明するこの記事ます。