サブクラス化
サブクラス化は、制限付きでサポートされています。最も重要なのは、**プロトタイプのアクション/フロー/計算値のみをオーバーライドできる**ことです - _フィールド宣言_ をオーバーライドすることはできません。サブクラスでオーバーライドされたメソッド/ゲッターには `override` アノテーションを使用してください - 以下の例を参照してください。物事をシンプルに保ち、継承よりもコンポジションを優先するようにしてください。
import { makeObservable, observable, computed, action, override } from "mobx"
class Parent {
// Annotated instance fields are NOT overridable
observable = 0
arrowAction = () => {}
// Non-annotated instance fields are overridable
overridableArrowAction = action(() => {})
// Annotated prototype methods/getters are overridable
action() {}
actionBound() {}
get computed() {}
constructor(value) {
makeObservable(this, {
observable: observable,
arrowAction: action
action: action,
actionBound: action.bound,
computed: computed,
})
}
}
class Child extends Parent {
/* --- INHERITED --- */
// THROWS - TypeError: Cannot redefine property
// observable = 5
// arrowAction = () = {}
// OK - not annotated
overridableArrowAction = action(() => {})
// OK - prototype
action() {}
actionBound() {}
get computed() {}
/* --- NEW --- */
childObservable = 0;
childArrowAction = () => {}
childAction() {}
childActionBound() {}
get childComputed() {}
constructor(value) {
super()
makeObservable(this, {
// inherited
action: override,
actionBound: override,
computed: override,
// new
childObservable: observable,
childArrowAction: action
childAction: action,
childActionBound: action.bound,
childComputed: computed,
})
}
}
制限事項
- **プロトタイプで定義された** `action`、`computed`、`flow`、`action.bound` **のみが**サブクラスによって**オーバーライド**できます。
- フィールドは、`override` を使用する場合を除き、サブクラスで再アノテーションできません。
- `makeAutoObservable` はサブクラス化をサポートしていません。
- 組み込み型 ( `ObservableMap`、`ObservableArray` など) の拡張はサポートされていません。
- サブクラスで `makeObservable` に異なるオプションを提供することはできません。
- 単一継承チェーンでアノテーション/デコレータを混在させることはできません。
- その他すべての制限も適用されます
`TypeError: Cannot redefine property`
これが表示された場合、おそらくサブクラス `x = () => {}` で**アロー関数をオーバーライドしようとしている**のでしょう。これは、クラスの**すべてのアノテーション付き**フィールドが**設定不可**であるため不可能です(制限事項を参照)。2 つのオプションがあります
1. 関数をプロトタイプに移動し、代わりに `action.bound` アノテーションを使用する
class Parent {
// action = () => {};
// =>
action() {}
constructor() {
makeObservable(this, {
action: action.bound
})
}
}
class Child {
action() {}
constructor() {
super()
makeObservable(this, {
action: override
})
}
}
2. `action` アノテーションを削除し、関数を手動でアクションでラップする: `x = action(() => {})`
class Parent {
// action = () => {};
// =>
action = action(() => {})
constructor() {
makeObservable(this, {}) // <-- annotation removed
}
}
class Child {
action = action(() => {})
constructor() {
super()
makeObservable(this, {}) // <-- annotation removed
}
}