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

1.4 POBP (Structures) Overview

Where the OOP part of CrxOop is an implementation of a pre existing paradigm, Structures are this author's vision, formalation, and generalization of prototypal inheritance and how it would work if javascript was a non scripting for rapid development, non strict, language like C++ or Java. In other words, structure are CrxOop's implementation of Prototype Based Programming, or as this author likes to call it, Prototype Object Based Programming (POBP).

Traditionaly, using plain javascript, different programmers resulted to different methods to implementing various features, such as private access, when coding prototype based data types. Each method had its own shortcoming, and non were complete. CrxOop introduces well defined fully functional implementation of POBP as this author envisions it. It should be noted that CrxOop's implementation is a super set of what traditionaly programmers envision when they apply their favorite method to code prototype based data types and the various effects that they want. CrxOop calls the prototype based data types, Structures.

1.4.1 Summary Of Supported Features

The following is a list of the high level features implemented in CrxOop for POPB, and an explanation for each.

  • Shared Public Scope (Variable): When a variable member has this scope, it is equivilant to setting the variable on 'this' in the constructor function when coding using plain javascript. Hence, the word 'shared' in the scope name. The variable is visible to all inheriting structures, and only one copy of it exists per instance. Shared public variables are supported on roughly IE9 era browsers and later.
  • Shared Public Scope (Function): When a function member has this scope, it is equivilant to setting the function on the prototype of the constructor function when coding using plain javscript. One, hence the word 'shared'. Two, there exists only one data entry for each function global to all objects of a particular prototype based data type. This would be contrary to setting the function on 'this' in the constructor function when coding using plain javascript.
  • Shared Private Scope (Variables and Functions): When a variable member, or a function member, has this scope the member can only be accessed on 'this'. If a structure 'A' defines the member 'x' with this scope, then only functions of 'A' can see 'x'. 'x' is private to 'A'. However, note the word 'shared'. If Structure 'B' inherits structure 'A', then functions of 'B' also have access to 'x'. But not only that, but also if 'A' itself inherits 'C', then functions of 'C' can also see 'x'. In other words, exactly like the shared public scope case, but only members of the structure chain of the instance may see 'x'. It should be noted, that this privacy is across instances, like in OOP. Refer to the structure keyword 'O'. Shared private variables are supported on roughly IE9 era browsers and later.
  • Private Scope (Variables and Functions): When a variable member, or a function member, has this scope the member can only be accessed on functions of the same structure. This is usualy enforced in plain javascript by declaring each such members as 'var' in the constructor function taking advantage of closures. However, unlike the plain javascript case, this privacy is across structure instances. Refer to the structure keyword 'O'.
  • Public Constructors: The public scope is supported for constructors only. The scope, and constructors act as expected when coding using plain javascript, but with the added benefit of the guaranteed default contstructor invocation like in the OOP case.
  • Multiple Inheritance.
  • Data Typing. See also Structrure Typing.
  • Iteration using the native javscript built "for in" loop mechanism. CrxOop provides HASOWN(), an equivilant to the built in hasOwnProperty().

1.4.2 POBP Syntax Overview

CrxOop's POBP facility offers two syntaxes for defining Structures, and one syntax for everything else. The following illustration should cover quickly most of the features supported, apart from iteration.

Figure 02: POBP Syntax Overview
JS (Tree)
crx_registerStructure('structureA',
{
   PUBLIC:
   {
      CONSTRUCT: function()
      {
         console.log('CONSTRUCTING A');
      }
   },
   PRIVATE:
   {
      VARS:
      {
         privateVar: "structureA::privateVar"
      },
      FUNCTIONS:
      {
         privateFunction: function()
         {
            return "structureA::privateFunction()";
         }
      }
   },
   SHARED:
   {
      PUBLIC:
      {
         VARS:
         {
            sharedPublicVar1: "structureA::sharedPublicVar1"
         },
         FUNCTIONS:
         {
            sharedPublicFunction1: function(pA)
            {
               console.log("I am structureA::sharedPublicFunction1() and I " +
                     "recieved parameter " + pA + " and I see " +
                     this.privateVar + " and " + this.privateFunction() + " and " +
                     this.sharedPublicVar1 + " and " + this.sharedPublicVar2 + " and " +
                     this.sharedPrivateVar1);
               console.log("---------");
            }
         }
      },
      PRIVATE:
      {
         VARS:
         {
            sharedPrivateVar1: "structureA::sharedPrivateVar1"
         },
         FUNCTIONS:
         {
            sharedPrivateFunction1: function(pA)
            {
               console.log("I am structureA::sharedPrivateFunction1() and I " +
                     "recieved parameter " + pA + " and I see " +
                     this.privateVar + " and " + this.privateFunction() + " and " +
                     this.sharedPublicVar1 + " and " + this.sharedPublicVar2 + " and " +
                     this.sharedPrivateVar1);
               console.log("---------");
            },
            sharedPrivateFunction2: function(pA)
            {
               console.log("I am structureA::sharedPrivateFunction2() and I " +
                     "recieved parameter " + pA + " and I see " +
                     this.privateVar + " and " + this.privateFunction() + " and " +
                     this.sharedPublicVar1 + " and " + this.sharedPublicVar2 + " and " +
                     this.sharedPrivateVar1);
               console.log("---------");
            }
         }
      }
   }
});
crx_registerStructure('structureB',
{
   PUBLIC:
   {
      CONSTRUCT: function()
      {
         console.log('CONSTRUCTING B');
      }
   },
   PRIVATE:
   {
      VARS:
      {
         privateVar: "structureB::privateVar"
      },
      FUNCTIONS:
      {
         privateFunction: function()
         {
            return "structureB::privateFunction()";
         }
      }
   },
   SHARED:
   {
      PUBLIC:
      {
         VARS:
         {
            sharedPublicVar2: "structureB::sharedPublicVar2"
         },
         FUNCTIONS:
         {
            test2: function(pStructureB_Or_C_Or_D)
            {
               console.log("I am structureB::test2() and I can see the private shared " +
                     "variable, that I defined, in another instance. The value is " +
                     this.O(pStructureB_Or_C_Or_D).sharedPrivateVar1);
               console.log("---------");
            }
         }
      },
      PRIVATE:
      {
         VARS:
         {
            sharedPrivateVar1: "structureB::sharedPrivateVar1"
         },
         FUNCTIONS:
         {
            sharedPrivateFunction2: function(pA)
            {
               console.log("I am structureB::sharedPrivateFunction2() and I " +
                     "recieved parameter " + pA + " and I see " +
                     this.privateVar + " and " + this.privateFunction() + " and " +
                     this.sharedPublicVar1 + " and " + this.sharedPublicVar2 + " and " +
                     this.sharedPrivateVar1);
               console.log("---------");
            }
         }
      }
   }
});
crx_registerStructure('structureC',
{
   INHERITS: ['structureB'],
   PUBLIC:
   {
      CONSTRUCT: function(pA)
      {
         console.log('CONSTRUCTING C: Passed ' + pA);
      }
   },
   PRIVATE:
   {
      VARS:
      {
         privateVar: "structureC::privateVar"
      },
      FUNCTIONS:
      {
         privateFunction: function()
         {
            return "structureC::privateFunction()";
         }
      }
   },
   SHARED:
   {
      PUBLIC:
      {
         VARS:
         {
            sharedPublicVar1: "structureC::sharedPublicVar1"
         }
      },
      PRIVATE:
      {
         VARS:
         {
            sharedPrivateVar1: "structureC::sharedPrivateVar1"
         }
      }
   }
});
crx_registerStructure('structureD',
{
   INHERITS: ['structureA', 'structureC'],
   PUBLIC:
   {
      CONSTRUCT: function(pA)
      {
         this.CONSTRUCT('structureC')(pA);
         console.log('CONSTRUCTING D');
      }
   },
   PRIVATE:
   {
      VARS:
      {
         privateVar: "structureD::privateVar"
      },
      FUNCTIONS:
      {
         privateFunction: function()
         {
            return "structureD::privateFunction()";
         }
      }
   },
   SHARED:
   {
      PUBLIC:
      {
         FUNCTIONS:
         {
            sharedPublicFunction1: function(pA)
            {
               console.log("I am structureD::sharedPublicFunction1() and I " +
                     "recieved parameter " + pA + " and I see " +
                     this.privateVar + " and " + this.privateFunction() + " and " +
                     this.sharedPublicVar1 + " and " + this.sharedPublicVar2 + " and " +
                     this.sharedPrivateVar1);
               console.log("---------");
            },
            test: function()
            {
               this.sharedPrivateFunction1(21);
               this.sharedPrivateFunction2(24);
               this.SR("structureA", "sharedPrivateFunction1", 28);
            }
         }
      },
      PRIVATE:
      {
         VARS:
         {
            sharedPrivateVar1: "structureD::sharedPrivateVar1"
         },
         FUNCTIONS:
         {
            sharedPrivateFunction1: function(pA)
            {
               console.log("I am structureD::sharedPrivateFunction1() and I " +
                     "recieved parameter " + pA + " and I see " +
                     this.privateVar + " and " + this.privateFunction() + " and " +
                     this.sharedPublicVar1 + " and " + this.sharedPublicVar2 + " and " +
                     this.sharedPrivateVar1);
               console.log("---------");
            }
         }
      }
   }
});

var a = crx_new("structureD", 123);

a.sharedPublicFunction1(10);
a.SR("structureA", "sharedPublicFunction1", 11);
a.test();
a.test2(crx_new("structureC", 99));
CONSTRUCTING C: Passed 123
CONSTRUCTING B
CONSTRUCTING D
CONSTRUCTING A
I am structureD::sharedPublicFunction1() and I recieved parameter 10 and I see structureD::privateVar and structureD::privateFunction() and structureC::sharedPublicVar1 and structureB::sharedPublicVar2 and structureD::sharedPrivateVar1
---------
I am structureA::sharedPublicFunction1() and I recieved parameter 11 and I see structureA::privateVar and structureA::privateFunction() and structureC::sharedPublicVar1 and structureB::sharedPublicVar2 and structureD::sharedPrivateVar1
---------
I am structureD::sharedPrivateFunction1() and I recieved parameter 21 and I see structureD::privateVar and structureD::privateFunction() and structureC::sharedPublicVar1 and structureB::sharedPublicVar2 and structureD::sharedPrivateVar1
---------
I am structureB::sharedPrivateFunction2() and I recieved parameter 24 and I see structureB::privateVar and structureB::privateFunction() and structureC::sharedPublicVar1 and structureB::sharedPublicVar2 and structureD::sharedPrivateVar1
---------
I am structureA::sharedPrivateFunction1() and I recieved parameter 28 and I see structureA::privateVar and structureA::privateFunction() and structureC::sharedPublicVar1 and structureB::sharedPublicVar2 and structureD::sharedPrivateVar1
---------
CONSTRUCTING C: Passed 99
CONSTRUCTING B
I am structureB::test2() and I can see the private shared variable, that I defined, in another instance. The value is structureC::sharedPrivateVar1
---------
JS (Verbose)
crx_registerStructure('structureA',
{
   VERBOSE: 1,
   "public CONSTRUCT": function()
   {
      console.log('CONSTRUCTING A');
   },
   "private var privateVar": "structureA::privateVar",
   "private function privateFunction": function()
   {
      return "structureA::privateFunction()";
   },
   "shared public var sharedPublicVar1": "structureA::sharedPublicVar1",
   "shared public function sharedPublicFunction1": function(pA)
   {
      console.log("I am structureA::sharedPublicFunction1() and I " +
            "recieved parameter " + pA + " and I see " +
            this.privateVar + " and " + this.privateFunction() + " and " +
            this.sharedPublicVar1 + " and " + this.sharedPublicVar2 + " and " +
            this.sharedPrivateVar1);
      console.log("---------");
   },
   "shared private var sharedPrivateVar1": "structureA::sharedPrivateVar1",
   "shared private function sharedPrivateFunction1": function(pA)
   {
      console.log("I am structureA::sharedPrivateFunction1() and I " +
            "recieved parameter " + pA + " and I see " +
            this.privateVar + " and " + this.privateFunction() + " and " +
            this.sharedPublicVar1 + " and " + this.sharedPublicVar2 + " and " +
            this.sharedPrivateVar1);
      console.log("---------");
   },
   "shared private function sharedPrivateFunction2": function(pA)
   {
      console.log("I am structureA::sharedPrivateFunction2() and I " +
            "recieved parameter " + pA + " and I see " +
            this.privateVar + " and " + this.privateFunction() + " and " +
            this.sharedPublicVar1 + " and " + this.sharedPublicVar2 + " and " +
            this.sharedPrivateVar1);
      console.log("---------");
   }
});
crx_registerStructure('structureB',
{
   VERBOSE: 1,
   "public CONSTRUCT": function()
   {
      console.log('CONSTRUCTING B');
   },
   "private var privateVar": "structureB::privateVar",
   "private function privateFunction": function()
   {
      return "structureB::privateFunction()";
   },
   "shared public var sharedPublicVar2": "structureB::sharedPublicVar2",
   "shared public function test2": function(pStructureB_Or_C_Or_D)
   {
      console.log("I am structureB::test2() and I can see the private shared " +
            "variable, that I defined, in another instance. The value is " +
            this.O(pStructureB_Or_C_Or_D).sharedPrivateVar1);
      console.log("---------");
   },
   "shared private var sharedPrivateVar1": "structureB::sharedPrivateVar1",
   "shared private function sharedPrivateFunction2": function(pA)
   {
      console.log("I am structureB::sharedPrivateFunction2() and I " +
            "recieved parameter " + pA + " and I see " +
            this.privateVar + " and " + this.privateFunction() + " and " +
            this.sharedPublicVar1 + " and " + this.sharedPublicVar2 + " and " +
            this.sharedPrivateVar1);
      console.log("---------");
   }
});
crx_registerStructure('structureC',
{
   VERBOSE: 1,
   INHERITS: ['structureB'],
   "public CONSTRUCT": function(pA)
   {
      console.log('CONSTRUCTING C: Passed ' + pA);
   },
   "private var privateVar": "structureC::privateVar",
   "private function privateFunction": function()
   {
      return "structureC::privateFunction()";
   },
   "shared public var sharedPublicVar1": "structureC::sharedPublicVar1",
   "shared private var sharedPrivateVar1": "structureC::sharedPrivateVar1"
});
crx_registerStructure('structureD',
{
   VERBOSE: 1,
   INHERITS: ['structureA', 'structureC'],
   "public CONSTRUCT": function(pA)
   {
      this.CONSTRUCT('structureC')(pA);
      console.log('CONSTRUCTING D');
   },
   "private var privateVar": "structureD::privateVar",
   "private function privateFunction": function()
   {
      return "structureD::privateFunction()";
   },
   "shared public function sharedPublicFunction1": function(pA)
   {
      console.log("I am structureD::sharedPublicFunction1() and I " +
            "recieved parameter " + pA + " and I see " +
            this.privateVar + " and " + this.privateFunction() + " and " +
            this.sharedPublicVar1 + " and " + this.sharedPublicVar2 + " and " +
            this.sharedPrivateVar1);
      console.log("---------");
   },
   "shared public function test": function()
   {
      this.sharedPrivateFunction1(21);
      this.sharedPrivateFunction2(24);
      this.SR("structureA", "sharedPrivateFunction1", 28);
   },
   "shared private var sharedPrivateVar1": "structureD::sharedPrivateVar1",
   "shared private function sharedPrivateFunction1": function(pA)
   {
      console.log("I am structureD::sharedPrivateFunction1() and I " +
            "recieved parameter " + pA + " and I see " +
            this.privateVar + " and " + this.privateFunction() + " and " +
            this.sharedPublicVar1 + " and " + this.sharedPublicVar2 + " and " +
            this.sharedPrivateVar1);
      console.log("---------");
   }
});

var a = crx_new("structureD", 123);

a.sharedPublicFunction1(10);
a.SR("structureA", "sharedPublicFunction1", 11);
a.test();
a.test2(crx_new("structureC", 99));
CONSTRUCTING C: Passed 123
CONSTRUCTING B
CONSTRUCTING D
CONSTRUCTING A
I am structureD::sharedPublicFunction1() and I recieved parameter 10 and I see structureD::privateVar and structureD::privateFunction() and structureC::sharedPublicVar1 and structureB::sharedPublicVar2 and structureD::sharedPrivateVar1
---------
I am structureA::sharedPublicFunction1() and I recieved parameter 11 and I see structureA::privateVar and structureA::privateFunction() and structureC::sharedPublicVar1 and structureB::sharedPublicVar2 and structureD::sharedPrivateVar1
---------
I am structureD::sharedPrivateFunction1() and I recieved parameter 21 and I see structureD::privateVar and structureD::privateFunction() and structureC::sharedPublicVar1 and structureB::sharedPublicVar2 and structureD::sharedPrivateVar1
---------
I am structureB::sharedPrivateFunction2() and I recieved parameter 24 and I see structureB::privateVar and structureB::privateFunction() and structureC::sharedPublicVar1 and structureB::sharedPublicVar2 and structureD::sharedPrivateVar1
---------
I am structureA::sharedPrivateFunction1() and I recieved parameter 28 and I see structureA::privateVar and structureA::privateFunction() and structureC::sharedPublicVar1 and structureB::sharedPublicVar2 and structureD::sharedPrivateVar1
---------
CONSTRUCTING C: Passed 99
CONSTRUCTING B
I am structureB::test2() and I can see the private shared variable, that I defined, in another instance. The value is structureC::sharedPrivateVar1
---------

1.4.2.1 Tree Syntax

Look at Figure 2, the Tree Syntax tab. There are Few things to note:

1.4.2.2 Verbose Syntax

Look at Figure 2, the Verbose Syntax tab. There are Few things to note:

1.4.3 Keywords

Refer back to Figure 2. CrxOop provides a number of 'keywords' to provide its functionality, most of which appear in the JS code in the figure. The 'keywords' fall under three types:

  • Definition Keywords: These keywords are available in structure definitions. In the tree syntax, they are object property names, and are case sensitive. In the verbose syntax they are part of object property names and are case insensitive apart for "VERBOSE" and "CONSTRUCT". Also note that in the CONSTRUCT, VARS, and FUNCTIONS.
  • Structure Keywords: These keywords are used in the structure instance functions, whether shared public, shared private, public, or prviate. They are property names of actual variables and functions placed on the object pointed to by the javascript keyword "this" in the instance function. Hence they are case sensitive. These keywords, along with the native "this", and apart from "THIS" must never be passed around as function parameters and function returns when accessed using "this". This rule also applies to the return of "O"(), i.e. the value returned by this.O().

    The following is the list of these keywords: O, THIS, CONSTRUCT, SR, and HASOWN.

  • Global Keywords: These keywords are global javascript functions that can be used any where, and hence they are case sensitive.

    The following is the list of these keywords: crx_registerStructure, and crx_new.

Keep in mind that all keywords, and typing functions which will be discussed later and are provided by CrxOop, can lead to fatal errors if used incorrectly. In other words, treat them all as actual keywords, the same way you do with native keywords in C++ and other languages. In other languages a misused keyword will either mean compilation failure, or runtime halt if the language is interpreted.