【问题标题】:What is the right way of doing Javascript static class inheritance with property override?使用属性覆盖进行 Javascript 静态类继承的正确方法是什么?
【发布时间】:2018-07-30 07:54:47
【问题描述】:

我发现了很多关于类继承的帖子,但没有关于更改静态类属性的具体问题。

问题是:我正在尝试在一个静态类上实现 JavaScript 上的类继承,该静态类将具有一些通用静态方法,并且将由子类扩展,静态也是如此。子类可能会添加更多静态方法并会更改配置对象。它们都不会被实例化,所以我假设我无法在构造函数上创建 body 属性,因为它不会被调用。我可以使用以下代码,但我认为这可能不是正确的方法。

你能推荐一个更好的选择吗?

class Animal{
    static get body(){
        return {
            legs: null,
            head: 1,
        }
    }
    static getLegs(){
        return this.body.legs;
    }
    static getHead(){
        return this.body.head;
    }
}
class Ant extends Animal{
    static get body(){
        return {
            legs: 6,
            head: 1,
        }
    }
}
class Monster extends Animal{
    static get body(){
        return {
            legs: 4,
            head: 2,
        }
    }
}
console.log(Animal.getLegs(), Animal.getHead());
console.log(Ant.getLegs(), Ant.getHead());
console.log(Monster.getLegs(), Monster.getHead());

【问题讨论】:

  • 代码正在运行,您的子类函数成功地隐藏了父类函数。我不确定您可能希望在这里改进什么?
  • @CertainPerformance 每次尝试获取正文时都会返回一个新对象,看起来性能不佳。我想知道是否有办法在构造之外使用变量或属性。

标签: javascript inheritance static


【解决方案1】:

classes 用于以更方便的方式创建继承原型的对象。实际上 JS 有原型继承(对象有原型),所以我们可以使用它:

 const animal = {
   body: { // you can fall back to a getter at any time
      legs: null,
      head: 1,
  },
  get legs(){
    return this.body.legs;
  },
  get head(){
    return this.body.head;
  }
};

const ant = Object.assign(Object.create(animal), {
  body: {
     legs: 6,
     head: 1,
  },
});

如果你需要这个类来做其他事情,你仍然可以设置一个属性:

 class Animal{
    static get legs(){
       return this.body.legs;
    }
    static get head(){
        return this.body.head;
    }
 }

Animal.body = { legs: null, head: 1, };

【讨论】:

  • 可以用类语法写吗?
  • @vandervals 是的,是的
  • 很好,谢谢!我想不出办法把那个body prop放在类声明里面,呵呵。这当然可以。
  • @vandervals 将来可能,静态类属性已经提出。
  • @JonasW。你真的可以用Object.create() 设置这样的属性吗?我虽然你需要body: value:{legs:6, head:1} 类似于属性描述符
【解决方案2】:

我不确定这个问题,但是如果你使用 Babel,你可以写这样的东西。

class Animal {
  static body = {
    legs: null,
    head: 1,
  };

  static getLegs() {
    return this.body.legs;
  }
  static getHead() {
    return this.body.head;
  }
}

class Ant extends Animal {
  static body = {
      legs: 6,
      head: 1
  };
}

class Monster extends Animal {
  static body = {
      legs: 4,
      head: 2,
  }
}
console.log(Animal.getLegs(), Animal.getHead());
console.log(Ant.getLegs(), Ant.getHead());
console.log(Monster.getLegs(), Monster.getHead());

【讨论】:

    【解决方案3】:

    如果您不想每次获取body 时都创建一个新对象,您可以将每个类的对象放入一个变量中并返回该变量。或者,您可以使用Map 使代码更清晰,它返回索引为this 的对象,只允许一个get body 定义:

    const { Animal, Ant, Monster } = (() => {
      class Animal {
        static get body() {
          return bodies.get(this)
        }
        static getLegs() {
          return this.body.legs;
        }
        static getHead() {
          return this.body.head;
        }
      }
      class Ant extends Animal {}
      class Monster extends Animal {}
      const bodies = new Map([
        [Animal, {
          legs: null,
          head: 1
        }],
        [Ant, {
          legs: 6,
          head: 1
        }],
        [Monster, {
          legs: 4,
          head: 2
        }]
      ]);
      return { Animal, Ant, Monster };
    })();
    console.log(Animal.getLegs(), Animal.getHead());
    console.log(Ant.getLegs(), Ant.getHead());
    console.log(Monster.getLegs(), Monster.getHead());

    IIFE 确保主体是半私有的(不过,如果对象本身被返回,它们仍然是可变的)。如果您还想防止对象在返回时发生变异,您可以使用Object.freeze。 (这并不能保证对象不会是可变的——如果明确地完成它们可以被解冻——但它会让意外突变的发生变得更加困难)

    【讨论】:

    • 好吧,与每个class 拥有get body 相比
    猜你喜欢
    • 1970-01-01
    • 2023-04-09
    • 2023-03-23
    • 1970-01-01
    • 2019-12-24
    • 1970-01-01
    • 1970-01-01
    • 2012-11-20
    • 2016-01-19
    相关资源
    最近更新 更多