强制子类是不可变的

时间:2017-05-29 14:24:51

标签: javascript oop typescript design-patterns immutable.js

我有一个带有一些属性的基类:

class Component {
    readonly id: number
    readonly type: number
}

我想要一些子类:

class HealthComponent extends Component {
    max_health: number,
    current_health: number
}

etc.

我想要的是HealthComponent基本上与Immutable.Record具有相同的行为:

const health = HealthComponent(100, 100);
health.max_health = 40; // Shouldn't work
const new_health = new HealthComponent(40, health.current_health); // Works

所有课程都只是数据;没有行为(如果有任何行为,它将在静态方法中,而不是实例方法)。现在我想尽可能强制执行子类是不可变的(在允许修改的意义上,但是使更改导致新对象或者将一个错误抛给了Immutable.js)并且我无法弄清楚这样做的最好方法。

我提出的最好的事情就是让每个子类都有一个只有data成员的Immutable.Record成员,其中包含相应的字段,但即使这样也不是非常正确,因为更改它会返回一个新的data对象,但我真的想要一个全新的Component对象,而且这并没有真正强制所有组件遵循这个约定。

我考虑过的另一件事是让基类成为Immutable.Record data: Immutable.Map字段,然后子类为Immutable.Map提供super带有所有键的构造函数,但是人们可以直接添加新的键,这也不是理想的。

是否有一种神奇的设计模式可以帮助我?

1 个答案:

答案 0 :(得分:0)

使用Readonly mapped type

class Component {
    constructor(public id: number, public type: number) {

    }
}

class HealthComponent extends Component {
    constructor(public id: number, public type: number, public max_health: number, public current_health: number) {
        super(id, type);
     }
}

let hc: Readonly<HealthComponent> = new HealthComponent(1, 2, 3, 4);
hc.max_health = 40; // Error

如果您没有行为,请考虑使用interface

interface Component {
    id: number
    type: number
}

interface HealthComponent extends Component {
    max_health: number;
    current_health: number;
}

let hc: Readonly<HealthComponent> = {
    id: 1,
    type: 2,
    max_health: 3,
    current_health: 4
};

hc.max_health = 40; // Error