代码之家  ›  专栏  ›  技术社区  ›  Vandervals

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

  •  0
  • Vandervals  · 技术社区  · 6 年前

    我发现了很多关于类继承的文章,但是没有涉及到在静态类上更改属性的这个特定问题。

    问题是:我试图在一个静态类上实现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 回复  |  直到 6 年前
        1
  •  1
  •   Hikmat G.    6 年前

    我不确定这个问题,但如果你用巴贝尔,你可以写这样的东西。

    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
  •  2
  •   Jonas Wilms    6 年前

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

     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, };
    
        3
  •  0
  •   CertainPerformance    6 年前

    如果不希望每次都创建新对象 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 . (那不是 保证 对象不会是可变的——如果显式地执行,它们可以被解冻——但这将使意外突变的发生更加困难)