CrxOop CrxOop: Bringing Object Oriented Programming, and Proper Prototype Based Programming, To Javascript
The aim of the library documented below is to provide developers with a solution to allow development using interfaces and classes as they are known in other object oriented programming (OOP) languages such as C++, C#, Java and PHP. Further more, V1.4 introduces structures, a generalization of the concept of prototypal inheritance, known here as POBP.
Subject
Body*
Email
SUBMIT CLOSE
Menu

3.4 Class Extension (aka Inheritance)

CrxOop supports single class inheritance, which will be called here class extension. Consider the following example:

JS (Tree)
crx_registerClass("ExampleClass1",
{
   PUBLIC:
   {
      VARS:
      {
         "publicVar": "I am ExampleClass1"
      },
      FUNCTIONS:
      {
         "publicFunction": function(pA)
         {
            console.log(this.publicVar);
         },
         "test": function(pA)
         {
            this.publicFunction();
            this.publicVirtualFunction();
            this.CAST("ExampleClass1").publicFunction(5);
            this.CAST("ExampleClass1").publicVirtualFunction(5);
            this.SR("ExampleClass1", "publicVirtualFunction", 5);
         }
      },
      VIRTUAL:
      {
         FUNCTIONS:
         {
            "publicVirtualFunction": function(pA)
            {
               console.log(this.publicVar);
            }
         }
      }
   }
});
crx_registerClass("ExampleClass2",
{
   EXTENDS: "ExampleClass1",
   PUBLIC:
   {
      VARS:
      {
         "publicVar": "I am ExampleClass2"
      },
      FUNCTIONS:
      {
         "publicFunction": function(pA)
         {
            console.log(this.publicVar);
         }
      },
      VIRTUAL:
      {
         FUNCTIONS:
         {
            "publicVirtualFunction": function(pA)
            {
               console.log(this.publicVar);
            }
         }
      }
   }
});

var instance = crx_new("ExampleClass2");

instance.publicFunction();
instance.publicVirtualFunction();
instance.CAST("ExampleClass1").publicFunction(5);
instance.CAST("ExampleClass1").publicVirtualFunction(5);
instance.SR("ExampleClass1", "publicVirtualFunction", 5);
console.log("------------------------------------------");
instance.test();
I am ExampleClass2
I am ExampleClass2
I am ExampleClass1
I am ExampleClass2
I am ExampleClass1
------------------------------------------
I am ExampleClass1
I am ExampleClass2
I am ExampleClass1
I am ExampleClass2
I am ExampleClass1
JS (Verbose)
crx_registerClass("ExampleClass1",
{
   VERBOSE: 1,
   "public var publicVar": "I am ExampleClass1",
   "public function publicFunction": function(pA)
   {
      console.log(this.publicVar);
   },
   "public function test": function(pA)
   {
      this.publicFunction();
      this.publicVirtualFunction();
      this.CAST("ExampleClass1").publicFunction(5);
      this.CAST("ExampleClass1").publicVirtualFunction(5);
      this.SR("ExampleClass1", "publicVirtualFunction", 5);
   },
   "public virtual function publicVirtualFunction": function(pA)
   {
      console.log(this.publicVar);
   }
});
crx_registerClass("ExampleClass2",
{
   VERBOSE: 1,
   "extends": "ExampleClass1",
   "public var publicVar": "I am ExampleClass2",
   "public function publicFunction": function(pA)
   {
      console.log(this.publicVar);
   },
   "public virtual function publicVirtualFunction": function(pA)
   {
      console.log(this.publicVar);
   }
});

var instance = crx_new("ExampleClass2");

instance.publicFunction();
instance.publicVirtualFunction();
instance.CAST("ExampleClass1").publicFunction(5);
instance.CAST("ExampleClass1").publicVirtualFunction(5);
instance.SR("ExampleClass1", "publicVirtualFunction", 5);
console.log("------------------------------------------");
instance.test();
I am ExampleClass2
I am ExampleClass2
I am ExampleClass1
I am ExampleClass2
I am ExampleClass1
------------------------------------------
I am ExampleClass1
I am ExampleClass2
I am ExampleClass1
I am ExampleClass2
I am ExampleClass1

Note the following:

  • The output by doing the tests on the instance is the same by doing the test using the function 'test' in the extended class except for the first line. This is because publicFunction is a non virtual function and hence it was publicFunction in side ExampleClass1 that was called when using 'this', where publicFunction inside class ExampleClass2 was called when using the variable "instance".
  • Notice how casting affects which "publicFunction" gets called. If the call is made on the variable "instance", which is an instance of ExampleClass2, ExampleClass2::publicFunction gets called and not ExampleClass1::publicFunction due to name hiding. If however it is casted to ExampleClass1 first, then ExampleClass1::publicFunction gets called.
  • Notice how casting does not affect which "publicVirtualFunction" gets called. This is because the function is virtual, and the call will always resolve to the most derived definition.
  • Some time you might want to call a virtual function, and or other variables found up the class chain, for this, CrxOop provides the class keyword 'SR'. The above example is likely self explanatory, but please see the section on 'SR' for more information.