9

I am asking how to implement the virtual function in the javascript like C#, let's say

  • I have a base class A
  • I also have a derived class named B
  • The class A has a function named virtualFunction, this is supposed to be a virtual function like in C#, this can be overridden in the derived class B
  • The function will be called to execute inside the constructor of the base class, A. If the function is overridden in B, B's one will be invoked otherwise A's one will be invoked

With this example below, I want to get a 'B' alert, not the 'A'.

function A() {
  this.virtualFunction();
}

A.prototype.virtualFunction = function() {
  alert('A');
};

//-------------------------------------

function B() {}

B.prototype = new A();
B.prototype.virtualFunction = function() {
  alert('B');
};

var b = new B();

If we invoke the function after instanced, like this, then it is okay, but I need "inside the constructor"

var b = new B();
b.virtualFunction();
ManoDestra
  • 6,325
  • 6
  • 26
  • 50
khoailang
  • 725
  • 1
  • 15
  • 32
  • 2
    In the first case you have `alert('A')` in both parent and child functions – MysterX Apr 19 '16 at 13:14
  • 4
    Even in C#, a base-class constructor doesn't have access to functions in a derived class. While the base constructor is running, the object is not an instance of the derived class yet, so the derived class's overrides haven not been set up yet. It wouldn't (in general) be safe anyway to call methods in the derived class before the derived constructor has run. – Wyzard Apr 19 '16 at 13:20
  • [Don't use new to create prototype objects!](https://stackoverflow.com/questions/12592913/what-is-the-reason-to-use-the-new-keyword-here) Instead, put a super call in `B`, and you'll get the expected results. – Bergi Apr 19 '16 at 13:35
  • @Bergi, thanks, I got your idea – khoailang Apr 19 '16 at 16:00

1 Answers1

10

So, the first thing to realize is that JavaScript doesn't use the same semantics as C#. Trying to get it to do so will cause you heartache; you're much better off learning how things are done in JS. In fact, most folks don't try to do a lot of inheritance type stuff in JS, but instead favor composition (which is actually a best practice in all OO languages I'm familiar with).

That said, there's a few improvements you could make to your code.

function A() {
  this.virtualFunction();
}

A.prototype.virtualFunction = function() {
  alert('A');
};

//-------------------------------------

function B() {
   A.call(this);
}

B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;
B.prototype.virtualFunction = function() {
  alert('B');
};

var b = new B();
Paul
  • 35,689
  • 11
  • 93
  • 122
  • thank you Paul, that is exactly what I want. I am just curious why we have to have the B.prototype.constructor = B; It still okay if I removed this line of code. When this is mandatory? – khoailang Apr 19 '16 at 16:27
  • If you don't, the constructor for B will be A, since this code sets all of B's prototype to a clone of A's prototype. Unlike in C#, the 'constructor' function is just another method on the prototype. – Paul Apr 19 '16 at 18:03
  • I marked as an answer since that is what I need, thank you. However, can you explain why I removed the B.prototype.constructor = B, that still be okay, works exactly the same, the 'constructor' B still be hit? Can you help me for an example that missing the B.prototype.constructor = B cause an error? – khoailang Apr 20 '16 at 04:27
  • There's cases where you'd actually want to call `this.constructor` and be sure it was calling the same function as you intended the constructor to be. – Paul Apr 20 '16 at 04:37
  • 2
    You can use `Object.setPrototypeOf` and ditch the constructor "fixing" since it won't replace the whole prototype object but only set the reference. – krulik Dec 18 '18 at 10:33