繁体   English   中英

Javascript:在子类中重写继承的方法后,如何运行父类的构造函数逻辑?

[英]Javascript: How to run constructor logic of parent class after overriding inherited methods in child class?

与面向类的语言相反,JS是基于原型的,对象的构造函数不仅包含“构造逻辑”(我在MDN上找到了这个术语),而且构造函数还定义了特权方法。 如果一个“类”是另一类的子类(对不起,我不知道比JS的“类”更好的术语),这将导致以下问题:要么在子类能够覆盖之前执行父构造函数方法或子类无法覆盖方法,因为构造函数尚未运行。

我将举一个例子来说明我的意思。 假设一个“父类”在对象上定义了一个特权函数,并调用了此方法的构造函数逻辑。

function Parent() {
  this.methodA = function() {
    // do something
  };

  // C'tor logic starts here
  // Beside other things also call some method of this object
  this.methodA();
}

假定一个子类应重新定义methodA但仍使用父类的构造函数逻辑。

第一种方法是在子构造函数的开头调用父构造函数。 但是,父级构造函数仍然会调用父级的实现。

Child.prototype = Object.create( Parent.prototype );
Child.prototype.constructor = Child;

function Child() {
  // Call parent constructor first. Problem: The parent constructor
  // calls methodA before it will be overriden by child constructor
  Parent.call( this );

  var _oldMethodA = this.methodA;
  this.methodA = function() {
    // do something special and then call parent method
    _oldMethodA.call( this );
  };
}

第二种方法是稍后调用父构造函数,但是,不能重写父方法。

Child.prototype = Object.create( Parent.prototype );
Child.prototype.constructor = Child;

function Child() {
  // Override first. Problem: The parent constructor has not defined methodA
  // yet, hence the line below fails.
  var _oldMethodA = this.methodA;
  this.methodA = function() {
    // do something special and call parent method
    _oldMethodA.call( this );
  };

  Parent.call( this );
}

如何交错JS构造函数的两个任务-特权方法的定义和构造函数逻辑-以正确的顺序调用?

附录-需要评论的其他材料

我从评论中发现,似乎不清楚我想要什么。 所以这是用Java编写的示例

class Parent {
  public Parent() { 
    methodA();
  }

  public void methodA() {
    System.out.println( "I do the work of the parent's method" );
  }
}

class Child extends Parent {
  public Child {
    super();
  }

  public void methodA() {
    System.out.println( "I do the work of the child's method and ..." );
    super();
  }
}

Parent p = new Parent();
Child c = new Child();

结果为以下输出

$> I do the work of the parent's method
$> I do the work of the child's method and ...
$> I do the work of the parent's method

这就是发生的情况。 的构造Parent呼吁实行methodA中定义Parent 这没什么特别的,它会产生第一行输出。 Child的构造函数只调用父级的构造函数,该构造函数再次像以前一样调用methodA 但是,尽管这是父级的构造方法,但是该对象仍然是Child的实例,因此将执行child类的methodA的实现。 此方法输出第二行输出,然后显式调用生成第三行的父级方法。

根据OOP,这是完美的正确行为,这也是我也希望使用Javascript实现的行为。 因此,实际上与这里提到的问题相反 链接来自评论。

您可以在调用父类之前将该属性定义为子类中的访问器。

这样,您将能够获得对父类分配的函数的引用,但仍可以在getter中提供所需的函数。

 function Parent() { this.methodA = function() { console.log('Parent method'); }; this.methodA(); } function Child() { var _oldMethodA; var _newMethodA = function() { console.log('Code injected by Child'); _oldMethodA.call( this ); }; Object.defineProperty(this, 'methodA', { configurable: true, enumerable: true, set: function(val){ _oldMethodA = val; }, get: function(){ return _newMethodA; } }); Parent.call(this); /* Optional: convert it back to a data property */ Object.defineProperty(this, 'methodA', { value: _newMethodA, writable: true }); } Child.prototype = Object.create( Parent.prototype ); Child.prototype.constructor = Child; new Child(); 

不确定您要在这里实现什么,但是一般来说您可以执行以下操作:

function Parent() {
  if (this.methodA == null) {
    this.methodA = function() {
      // do something
      console.log('parent');
    };
  }

  // C'tor logic starts here
  // Beside other things also call some method of this object
  this.methodA();
}

function Child() {

  this.methodA = (function(_oldMethodA) {
    return function() {
      console.log('child');
      // do something special and then call parent method
      if (_oldMethodA) {
        _oldMethodA.call( this );
      }
    }
  })(this.methodA);

  Parent.call( this );
}

Child.prototype = Object.create( Parent.prototype );
Child.prototype.constructor = Child;

new Child(); // yields: 'child'

但是判断您要执行的操作时,可能要在父级中添加一些数组,这是您在父类中覆盖methodA

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM