如何从 JavaScript 中的父类访问私有字段?

Posted

技术标签:

【中文标题】如何从 JavaScript 中的父类访问私有字段?【英文标题】:How to access private fields from parent class in JavaScript? 【发布时间】:2021-12-15 19:02:38 【问题描述】:

我有一个 Heap 类,它有一个私有 values 字段。这很好,因为我不希望任何人能够直接修改values

class Heap 
  
  #values;
  
  constructor(array = []) 
    this.#values = array;
  

    insert(item) 
    this.#values.push(item);
    this.#bubbleUp(this.#values.length - 1);
  

但现在我想将我的 Heap 类扩展为 PriorityQueue 子类。在这个类中,我需要更改一些方法的签名(例如insert),以便它为一个值分配一个优先级。但是,我无法弄清楚如何从基类访问 values 字段。例如,给定以下 PriorityQueue 类:

class PriorityQueue extends Heap 
  
  constructor(array = []) 
    super(array);
  
  
  insert(item, priority) 

    // Error: Private field '#values' must be declared in an enclosing class
    this.#values.push( item, priority ); 
    this.#bubbleUp(this.#values.length - 1);
  

尝试将值推送到 values 时出现错误。

有没有办法解决这个问题?我想在基类中将一个字段设为私有,但子类仍然可以访问。

谢谢!

【问题讨论】:

只调用父级的insert方法? super.insert( item, priority ). 我想在基类中将一个字段设为私有,但子类仍然可以访问。”这就是受保护的访问。但是,JS 目前还没有。所以你想在子类中使用的任何东西都必须是公开的。 【参考方案1】:

我不知道如何从基类访问values 字段。

这是不可能的。私有在 JS 中真正意味着私有。如果您希望该字段可在课堂外访问,请不要使用它。

我想在基类中将一个字段设为私有,但子类仍然可以访问。

这将是一个受保护的成员,JS 不支持。

有没有办法解决这个问题?

好吧,您实际上并不需要访问.#values。您需要做的就是调用基类insert 方法:

class PriorityQueue extends Heap  
  insert(item, priority) 
    super.insert( item, priority );
  

我想将我的 Heap 类扩展为 PriorityQueue 子类。在这个类中,我需要更改一些方法的签名(例如插入),以便它为一个值分配优先级。

这是个坏主意。子类不应更改方法签名,否则将违反Liskov substitution principle。相反,请使用composition over inheritance,其中优先级队列具有包含堆:

class PriorityQueue 
  #heap = new Heap(v => v.priority); // assuming it takes a custom comparator?
  
  push(item, priority) 
    this.#heap.insert( item, priority );
  
  pop() 
    return this.#heap.…
  

【讨论】:

感谢您的回答,您的帖子很有帮助。我的Heap 类确实使用了比较器。我什至从未考虑过将 PriorityQueue 构造为具有堆实例,而不是从 Heap 类继承。我显然有很多东西要学。顺便说一句,您是否推荐任何书籍来学习诸如组合优于继承之类的主题?

以上是关于如何从 JavaScript 中的父类访问私有字段?的主要内容,如果未能解决你的问题,请参考以下文章

无法访问kotlin子类中的父类变量

python中类成员修饰符

子类从 Java 中的父类更改受保护的变量

从子类访问父类的私有实例变量?

接口3

如何从 React 中的父类更新我的子组件状态?