访问从基类构造函数调用的重写方法中的私有方法

Posted

技术标签:

【中文标题】访问从基类构造函数调用的重写方法中的私有方法【英文标题】:Access private method in an overriden method called from the base class constructor 【发布时间】:2020-07-28 22:04:48 【问题描述】:

考虑以下代码:

class MyBase 
  constructor(b) 
    this.myOverrideMethod(b);
  
  myOverrideMethod(b) 

class MyClass extends MyBase 
  constructor(b) 
    super(b);
  
  myOverrideMethod(b) 
    if (b) 
      this.mySpecificMethod();
     else 
      this.#myPrivateMethod();
    
  
  mySpecificMethod() 
    console.log('mySpecificMethod');
  
  #myPrivateMethod = () => 
    console.log('#myPrivateMethod');
  ;

new MyClass(true);  // <-- "mySpecificMethod"
new MyClass(false); // <-- Uncaught TypeError: Cannot read private member #myPrivateMethod 
                    //     from an object whose class did not declare it

myOverrideMethod() 的重写方法在“基”类的构造函数中调用。由于this 指向MyClass 的一个实例,所以派生类中被覆盖的方法被正确调用。 mySpecificMethod() 的常规方法调用成功,而调用#myPrivateMethod() 的私有字段会抛出以下“TypeError”:

未捕获的类型错误:无法从类未声明的对象中读取私有成员 #myPrivateMethod

错误消息并未将问题传达为私有字段访问冲突,而是唤起了this 尚未引用MyClass 的实例但仍引用@ 的实例987654330@!但是,这是为什么呢?如何成功调用#myPrivateMethod()的私有方法呢?

【问题讨论】:

永远不要从构造函数中调用可覆盖的方法,也不要为方法使用类字段。 【参考方案1】:

这只是在构造函数期间尝试调用私有方法时出现的问题。我认为是因为子类在父类的构造函数中还没有完全构造好,所以私有方法还不可用。

看下面的例子,我从普通方法调用this.myOverrideMethod(),并且允许调用。

class MyBase 
  constructor() 
  
  doit(b) 
    this.myOverrideMethod(b);
  
  myOverrideMethod(b) 

class MyClass extends MyBase 
  constructor() 
    super();
  
  myOverrideMethod(b) 
    if (b) 
      this.mySpecificMethod();
     else 
      this.#myPrivateMethod();
    
  
  mySpecificMethod() 
    console.log('mySpecificMethod');
  
  #myPrivateMethod = () => 
    console.log('#myPrivateMethod');
  ;

new MyClass().doit(true);
new MyClass().doit(false);

【讨论】:

感谢您的回复,没错,问题仅在于“构造函数”;奇怪的是,虽然 “子类尚未完全构建” 但它仍然可以解决“常规”方法而不是“私有”方法!同样不幸的是,我的具体情况是一个复杂的层次结构,其中调用堆栈必须通过构造函数,并且在获得“完全构造”之后无法通过代理方法完成。 私人方法可能太新,以至于没有太多的细微差别经验。 @dev2020 可以解析原型方法,不能解析实例方法。这与他们是否私密无关。 为什么它适用于mySpecificMethod?它是一个实例方法,不是吗? @Bergi 它确实解决了 “私有实例字段”,但只有在“完全构造”之后(正如 Barmar 在这个答案中指出的那样)。正如我在原始帖子中所述,这不是超出范围的访问冲突错误;而是,将流程放在基类构造函数中,与派生类实例构造相对应的部分尚未达到,因此出现错误,而显然“原型方法”已经在进入之前处理用于构造的类继承层次结构!!

以上是关于访问从基类构造函数调用的重写方法中的私有方法的主要内容,如果未能解决你的问题,请参考以下文章

从基类构造函数调用纯虚函数

C++中子类从基类都继承啥?

C# 中base和this关键字

尝试从基类访问受保护的构造函数时获取错误C2248

如何从基类调用派生赋值运算符?

从基类调用重写的方法