js/ts 中 setter 和 getter 的抽象泄漏

问题描述 投票:0回答:1

我正在开发一款游戏。因为我不想与框架结合,所以我为图形引擎编写了一个抽象,现在正尝试将 Three.js 塞入其中。

我正在使用 gl-matrix 进行向量数学(使用

vec3
,类型化数组), Three.js 有自己的向量类(使用
{x:number, y:number, z:number}
)。我的 3D 对象界面如下所示:

interface Thing{
    ...
    position:vec3
}

我的实现如下所示:

class ThreeJsThing implements Thing{
    ...
    set position(p:vec3){
        this.mesh.position.set(p[0], p[1], p[2]) // [,,] -> {xyz}
    }
    get position(){
        let p = this.mesh.position
        return vec3.fromValues(p.x, p.y, p.z) // {xyz} -> [,,]
    }
}

现在一切都很有趣和游戏,直到有人尝试这样做:

let myThing = new ThreeJsThing()
myThing.position[1] = 5 // only changes a temporary copy that is returned by the getter

对于 gl-matrix 这尤其是一个问题,因为它出于性能原因使用输出参数,在内部执行上面的数组分配:

vec3.add(myThing.position, a, b)

我知道如何解决这个问题,因为我(现在)意识到了它,但其他贡献者可能也会对此感到窒息,特别是因为它默默地失败了。仅从干净的代码角度来看,我无法真正确定我在哪里使用了反模式或糟糕的设计或其他东西。我发现

ThreeJsThing
尽可能忠实于界面。我有一些怀疑:

  • 也许这只是 set 和 get 的普遍问题,应该避免它们?
  • 也许 set 和 get 不应该进行复制,而只接受/返回并在内部使用相同类型的引用?
  • 输出参数不受欢迎(但
    myThing.position[1] = 5
    仍然是一个问题)

任何建议表示赞赏。

javascript getter-setter leaky-abstraction
1个回答
0
投票

我建议返回一个抽象而不是

vec3.fromValues
...

除非你真的需要它作为 vec3...

喜欢:

class ThreeJsThing implements Thing
{
    // ...
    
    set position ( p: vec3 )
    {
        this.mesh.position.set(p[0], p[1], p[2]) // [,,] -> {xyz}
    }
    
    get position ()
    {
        const p = this.mesh.position;
        
        const o =
        {
            length: 3,
            
            get 0 () { return p.x }
            set 0 (n) { p.set(n, p.y, p.z) }
            
            get 1 () { return p.y }
            set 1 (n) { p.set(p.x, n, p.z) }
            
            get 2 () { return p.z }
            set 2 (n) { p.set(p.x, p.y, n) }
        };
        
        Object.setPrototypeOf(o, Array.prototype);
        
        return o // {xyz} -> [,,]
    }
}

PS.:我不是 TS 方面的专家,所以也许有问题......但我希望你明白。

© www.soinside.com 2019 - 2024. All rights reserved.