用属性重写进行Javascript静态类继承的正确方法是什么?

时间:2018-07-30 07:54:47

标签: javascript inheritance static

我发现了很多关于类继承的文章,但关于改变静态类的属性这一特定问题却不是。

这是问题所在:我正在尝试在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());

3 个答案:

答案 0 :(得分:2)

class可以用来创建对象,从而以更方便的方式继承原型。实际上,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, };

答案 1 :(得分:1)

我不确定这个问题,但是如果您使用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());

答案 2 :(得分:0)

如果不想每次获取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。 (这并不能保证对象不会发生变化-如果显式完成,则可以取消冻结这些对象-但这会使意外突变的发生更加困难)