Некоторый код может сказать больше, чем тысяча слов:Создание объекта одного и того же класса: Javascript прототип, частные члены, наследование
/**
* 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 считаются незыблемыми. Они возвращают новый объект при операции добавления. Теперь вместо того, чтобы просто вызвать «новый ресурс (args)», чтобы создать новый объект для возврата, я создал новый, основанный на старом объекте. Это также позволяет наследовать.
Поскольку я начинаю использовать это во всех моих 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. Их частные члены неизменны. Но как насчет сменных частных членов? Если на clone вызывается set(), он устанавливает оригинальный прототип объекта в закрытии! Поскольку мой Object.recreate воссоздает закрытие, эта проблема решена.
Так есть ли лучший способ для наследования с частными переменными? Почему все используют сахар для создания классов? Я так много читал о прототипализме, но до сих пор не знаю.
Хорошая статья, но я не мог получить много нового. owl.clone - это именно то, что Object.create здесь, и я думаю, что это имя лучше подходит. Я отредактирую свой вопрос для случая non-ValueObjects с частными переменными, которые сталкиваются с «clone/create», но не с моим воссозданием. – Phoscur