Создайте объект того же класса: прототип Javascript, закрытые члены, наследование - PullRequest
0 голосов
/ 17 февраля 2010

Некоторые коды могут произносить более тысячи слов:

/**
 * 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;
};

Объектами ресурса являются объекты ValueObject, которые считаются неизменяемыми. Они возвращают новый объект в операции сложения. Теперь вместо того, чтобы просто вызывать «new Resource (args)» для создания возвращаемого нового объекта, я создал новый на основе старого объекта. Это также разрешает наследование.

Поскольку я начинаю использовать это на всех своих объектах ValueObject (на всякий случай, когда я хочу наследовать от них в будущем), я начал думать об этом немного больше.

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. Их частные члены неизменны. Но как насчет сменных частных членов? Если set () вызывается для клона, он устанавливает исходный объект-прототип в замыкании! Когда мой Object.recreate воссоздает замыкание, эта проблема решена.

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

Ответы [ 2 ]

0 голосов
/ 29 декабря 2017

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

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

Используйте композицию поверх наследования! Крокфорд дает отличное понимание JavaScript: https://crockford.com/javascript/prototypal.html

0 голосов
/ 17 февраля 2010

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

...