Каков наилучший способ обобщить типизированные сеттеры и геттеры?

1

Каков наилучший способ обобщить сеттеры и геттеры в этом классе:

class A {
    constructor() {
        this._foo = new Foo();
        this._bar = new Bar();
    }

    get foo() {
        return this._foo;
    }

    set foo(value) {
        if (value instanceof Foo)
            this._foo = value;
        else
            this._foo = Object.assign(new Foo(), value);
    }

    get bar() {
        return this._bar;
    }

    set bar(value) {
        if(value instanceof Bar)
            this._bar = value;
        else
            this._bar = Object.assign(new Bar(), value);
    }
}

редактировать

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

Мне нужны эти сеттеры для определения типа членов после десериализации документа json, сохраненного в базе данных:

{
    "foo" :{"x":0,"y":0,"z":0},
    "bar" : {"propA": "valueA", "propB": "valueB"}
}
  • 0
    Не иметь их вообще и использовать какую-то систему типов (машинопись, поток ...)
  • 5
    Я не уверен, что вы подразумеваете под "напечатанным" или что вы подразумеваете под "обобщенным" ...
Показать ещё 3 комментария
Теги:
ecmascript-6

2 ответа

2

Вы можете теоретически использовать миксин:

 const Typed = (key, type, parent = class {}) => class Typed extends parent {
   constructor(...props) {
    super(...props);
     this['_${key}'] = new type();
   }

  get [key]() { return this['_${key}']; }

  set [key](value) { 
      this['_${key}'] = value instanceof type ? value : Object.assign(new type, value);
  }
}

const A = Typed("foo", Foo, Typed("bar", Bar, class {
 //...
});

Но вам, вероятно, не следует вообще использовать getter/setters, а скорее исправить код, который пытается установить свойство с недопустимыми значениями.

  • 2
    Я бы не сказал, что код, который устанавливает «недопустимые значения», обязательно сломан. Я вижу вескую причину иметь это. Опять же, я не знаю, было ли это принято дизайнерским решением или применено исправление постфактум. Если это последнее, то решение действительно состоит в том, чтобы исправить это и, возможно, даже ввести проверку типов в систему.
  • 0
    Мне нужно установить тип членов после десериализации документа json, сохраненного в базе данных
0

Если вы хотите абстрагировать создание сеттеров/геттеров, вы, конечно, можете написать функцию, которая сделает это:

function typedAccessor(obj, name, type, internal) {
    Object.defineProperty(obj, name, {
        get() {
            return this[internal];
        },
        set(val) {
            if (val instanceof type)
                this[internal] = val;
            else
                this[internal] = Object.assign(new type, val);
        }
    });
}

class A {
    constructor() {
        this._foo = new Foo();
        this._bar = new Bar();
    }
}
typedAccessor(A.prototype, "foo", Foo, "_foo");
typedAccessor(A.prototype, "bar", Bar, "_bar");

Однако я бы порекомендовал избегать этого паттерна.

Мне нужны эти сеттеры, чтобы определить тип членов после десериализации документа json

Лучше использовать пользовательский статический метод, который знает, как работать с представлениями JSON, чем делать Object.assign (и надеяться, что все имеет правильные установщики). Это дает вам намного лучший контроль над процессом сериализации/десериализации и делает ваш класс проще, с меньшим количеством стандартного кода.

class A {
    constructor(foo, bar) {
        this.foo = foo;
        this.bar = bar;
    }
    static fromJSON(val) {
        return new this(Foo.fromJSON(val.foo), Bar.fromJSON(val.bar);
    }
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню