2

我想从派生类访问基类的私有字段而不将它们公开(在其他语言中称为“受保护”)。

考虑以下类:

class Animal {

  #privateProp;

  constructor() {

  this.#privateProp = 12;

  }
}

现在扩展类:

class Cat extends Animal {

  constructor() {

    super();
  }

  doIt() {

    console.log(this.#privateProp) // 1 below
    console.log(super.#privateProp) // 2 below
  }
}

我想像受到保护一样执行:

new Cat().doIt();

但是得到(分别):

  1. 未捕获的语法错误:必须在封闭类中声明私有字段“#privateProp”
  2. 未捕获的 SyntaxError:意外的私有字段

请注意,当 privateProp 公开时,此代码将完美运行,但我想实现类似受保护的行为并像任何支持继承的语言一样访问“私有”字段。

任何帮助将不胜感激。

4

2 回答 2

1

您可以通过检查构造函数是否不属于父类本身来创建具有受限访问权限的 getter 和 setter 方法的私有属性。

class Animal {
  #privateProp = 12;
  set Prop(val) {
    if (this.constructor.name !== 'Animal')
      return this.#privateProp = val;
    throw new Error('Cannot Access Protected property');
  }
  get Prop() {
    if (this.constructor.name !== 'Animal')
      return this.#privateProp;
    throw new Error('Cannot Access Protected property');
  }
}

class Cat extends Animal {
  get Prop() {
    return super.Prop;
  }

  set Prop(val) {
    super.Prop = val
  }
}

let cat = new Cat();
console.log(cat.Prop)
cat.Prop = 22
console.log(cat.Prop)

console.log(new Animal().Prop);

于 2020-04-15T20:18:40.590 回答
1

字段是私有的,类似于变量是块作用域的;如果某个属性是某个特定的私有属性class,则它只能在该类中被引用。如果您扩展该类,它将在派生类中不可见。

如果您希望能够从子类中使用它,您可以在超类上创建一个 getter/setter:

class Animal {
  #privateProp = 12;
  setProp(val) {
    this.#privateProp = val;
  }
  getProp() {
    return this.#privateProp;
  }
}
class Cat extends Animal {
  doIt() {
    console.log(this.getProp());
  }
}
new Cat().doIt();

另一种方法是将“私有”字段定义为仅适用于类声明的 WeakMap:

const { Animal, Cat } = (() => {
  const privateProps = new WeakMap();
  class Animal {
    constructor() {
      privateProps.set(this, 12);
    }
  }
  class Cat extends Animal {
    doIt() {
      console.log(privateProps.get(this));
    }
  }
  return { Animal, Cat };
})();
new Cat().doIt();

于 2020-04-15T09:25:18.373 回答