我有3个班级,都扩展了上一个班级。
实体->身体->播放器
每个人都有一个die()
方法,它们的作用截然不同。
Entity.die()
将调用数据库
Body.die()
将为身体设置动画
Player.die()
将调用UI并播放特殊声音。
我不想在Entity.die()
方法内手动调用Body.die
,主要是因为我有很多类和很多常用方法,而且我也不想忘记什么。
我写了这段代码来完成此操作,错误堆栈很容易理解,并指向正确的行。
function overLoadMethods (parent, children) {
const methods = {}
for (let [fname, fn] of Object.entries(parent)) {
if (typeof fn === 'function') {
if (children[fname]) {
methods[fname] = function () {
fn()
children[fname]()
}
Object.defineProperty(methods[fname], 'name', { value: fname })
} else {
methods[fname] = fn
}
}
}
return methods
}
function createEntity () {
return {
die: () => {
console.log(new Error().stack)
console.log('entity die')
}
}
}
const bodyMethods = {
die: () => {
console.log(new Error().stack)
console.log('body die')
}
}
function createBody () {
const entity = createEntity()
const overLoadedMethods = overLoadMethods(entity, bodyMethods)
return {
...entity,
...bodyMethods,
...overLoadedMethods
}
}
const playerMethods = {
die: () => {
console.log(new Error().stack)
console.log('player die')
}
}
function createPlayer () {
const body = createBody()
const overLoadedMethods = overLoadMethods(body, playerMethods)
return {
...body,
...playerMethods,
...overLoadedMethods
}
}
const player = createPlayer()
// will call Entity.die() then Body.die() then Player.die()
player.die()
一切正常,但我以前从未见过这种模式,我想这是我不知道的充分理由。 有人可以指出这种模式的弱点吗(肯定有)?
答案 0 :(得分:1)
我理解不重复代码和创建代码的愿望,这使得代码难以出错和遗忘。但是您仍然有需要记住的代码。例如,您不必呼叫Entity.die()
,而需要呼叫overLoadMethods()
。我不确定这是否优于常规类和调用super.die()
。
您可以使用ES6类获得链式方法的行为(也可以使用原型获得它)。这有很多优点:
•模式已融入语言。
•很明显看到父母/孩子的关系
•有很多关于不同模式的评论,理论和例子
class Entity {
die() {
// Entity-specific behavior
console.log('entity die')
}
}
class Body extends Entity {
die() {
super.die()
// Body-specific behavior
console.log('body die')
}
}
class Player extends Body {
die() {
super.die()
// Player-specific behavior
console.log('player die')
}
}
const player = new Player
// will call Entity.die() then Body.die() then Player.die()
player.die()
答案 1 :(得分:1)
通用Lisp有something similar。在派生类中定义方法时,可以决定是否应执行此方法:
:before
(即在专门的方法之后将自动调用基本方法):after
(即基本方法将在专用方法之前自动调用):around
(即,仅将调用专用方法,但是您可以在其主体内部使用call-next-method
调用基本方法,这是一种特殊语法,允许使用由指定的参数调用基本方法调用方或您要传递的参数。例如,C ++仅将around
用于常规方法(但不能使用原始参数调用基本版本),并强制在构造函数中使用before
,在构造函数中使用after
破坏者。