2010-02-17 3 views
0

Некоторый код может сказать больше, чем тысяча слов:Создание объекта одного и того же класса: 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 воссоздает закрытие, эта проблема решена.

Так есть ли лучший способ для наследования с частными переменными? Почему все используют сахар для создания классов? Я так много читал о прототипализме, но до сих пор не знаю.

ответ

0

Возвращаясь к этому через несколько лет, я могу сказать, что код, который я написал, был ошибочным в смешении концепций. JavaScript может фактически предоставлять истинные частные переменные путем закрытия. Но так как ValueObjects неизменны в любом случае, это частное состояние не может быть изменено, и это слишком усложняет вещи, чтобы скрыть это.

Кроме того, гениальный Object.recreate является своего рода чрезмерно абстрагированным «заводским методом», который нужно отдельно разделить на каждый класс, если он ему нужен.

Использование композиции над наследованием! Crockford дает отличные оценки JavaScript: https://crockford.com/javascript/prototypal.html

0

Я думаю, что копия или клон будет лучшим именем. В этом article объясняются механизмы создания таких общих функций.

+0

Хорошая статья, но я не мог получить много нового. owl.clone - это именно то, что Object.create здесь, и я думаю, что это имя лучше подходит. Я отредактирую свой вопрос для случая non-ValueObjects с частными переменными, которые сталкиваются с «clone/create», но не с моим воссозданием. – Phoscur

Смежные вопросы