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.6.7 SR

"SR" stands for Scope Resolver and is roughly the equivilant of "::" in C++. However, it can only be used on instances, and up the extension chain. It can be used to access virtual, and non virtual, non static, members of the class. Its use should generally be kept to a minimum, but is provided here for when needed.

"SR", like "O" for example, must never be passed to functions as parameters, or returned from functions as returns. "SR" will cause fatal errors if the class is not in the instance's class extension chain at all, or if misused.

JS (Tree)
crx_registerClass("ExampleClass1",
{
   PUBLIC:
   {
      VARS:
      {
         "publicVar": "I am ExampleClass1",
      },
      VIRTUAL:
      {
         FUNCTIONS:
         {
            "pulicVirtualFunction": function(pA)
            {
               console.log(this.publicVar);
            }
         }
      },
      FUNCTIONS:
      {
         "pulicFunction": function(pA)
         {
            console.log("From ExampleClass1::publicFunction: " + this.publicVar);
         }
      }
   }
});
crx_registerClass("ExampleClass2",
{
   EXTENDS: "ExampleClass1",
   PUBLIC:
   {
      VARS:
      {
         "publicVar": "I am ExampleClass2",
      },
      VIRTUAL:
      {
         FUNCTIONS:
         {
            "pulicVirtualFunction": function(pA)
            {
               console.log(this.publicVar);
            }
         }
      },
      FUNCTIONS:
      {
         "pulicFunction": function(pA)
         {
            console.log("From ExampleClass2::publicFunction: " + this.publicVar);
         }
      }
   }
});
crx_registerClass("ExampleClass3",
{
   EXTENDS: "ExampleClass2",
   PUBLIC:
   {
      VARS:
      {
         "publicVar": "I am ExampleClass3",
      },
      VIRTUAL:
      {
         FUNCTIONS:
         {
            "pulicVirtualFunction": function(pA)
            {
               console.log(this.publicVar);
            }
         }
      },
      FUNCTIONS:
      {
         test: function(pA)
         {
            //   Calling ExampleClass1::pulicVirtualFunction
            //      using CAST will not work with virtual
            //      functions.
            this.CAST("ExampleClass1").pulicVirtualFunction(5);
            //   Instead we have to use 'SR'
            this.SR("ExampleClass1", "pulicVirtualFunction", 5);

            //   The following would call
            //      ExampleClass2::pulicVirtualFunction
            this.SR("ExampleClass2", "pulicVirtualFunction", 5);

            //   The following is equivalent to the above because 'null'
            //      automatically resolves to the parent of the instance's
            //      class, which in the case of 'this' is ExampleClass2.
            this.SR(null, "pulicVirtualFunction", 5);

            //   Trying to call ExampleClass1::pulicFunction using the following
            //      will not work because of name hiding caused by the existance
            //      of ExampleClass2::pulicFunction
            this.pulicFunction(5);
            //   Instead we have to use 'SR'
            this.SR("ExampleClass1", "pulicFunction", 5);

            //   The same problem exists for ExampleClass1::publicVar, and hence the
            //      the following will not work, reading and writing to
            //      ExampleClass2::publicVar instead.
            console.log(this.publicVar);
            this.publicVar = "FIRST CHANGE";
            //   Instead we have to use 'SR'
            console.log(this.SR("ExampleClass1", "publicVar"));
            this.SR("ExampleClass1", "publicVar", "SECOND CHANGE");

            //   Printing the result of the above
            console.log("------------------");
            console.log(this.publicVar);
            console.log(this.SR("ExampleClass2", "publicVar"));
            console.log(this.SR("ExampleClass1", "publicVar"));
         }
      }
   }
});

var instance = crx_new("ExampleClass3");

instance.test();

//SR is also available on the instance
console.log("------------------");
instance.SR("ExampleClass1", "pulicVirtualFunction", 5);
I am ExampleClass3
I am ExampleClass1
I am ExampleClass2
I am ExampleClass2
From ExampleClass2::publicFunction: I am ExampleClass2
From ExampleClass1::publicFunction: I am ExampleClass1
I am ExampleClass3
I am ExampleClass1
------------------
FIRST CHANGE
I am ExampleClass2
SECOND CHANGE
------------------
SECOND CHANGE
JS (Verbose)
crx_registerClass("ExampleClass1",
{
   "VERBOSE": 1,
   "public var publicVar": "I am ExampleClass1",
   "public virtual function pulicVirtualFunction": function(pA)
   {
      console.log(this.publicVar);
   },
   "public function pulicFunction": function(pA)
   {
      console.log("From ExampleClass1::publicFunction: " + this.publicVar);
   }
});
crx_registerClass("ExampleClass2",
{
   "VERBOSE": 1,
   "extends": "ExampleClass1",
   "public var publicVar": "I am ExampleClass2",
   "public virtual function pulicVirtualFunction": function(pA)
   {
      console.log(this.publicVar);
   },
   "public function pulicFunction": function(pA)
   {
      console.log("From ExampleClass2::publicFunction: " + this.publicVar);
   }
});
crx_registerClass("ExampleClass3",
{
   "VERBOSE": 1,
   "extends": "ExampleClass2",
   "public var publicVar": "I am ExampleClass3",
   "public virtual function pulicVirtualFunction": function(pA)
   {
      console.log(this.publicVar);
   },
   "public function test": function(pA)
   {
      //   Calling ExampleClass1::pulicVirtualFunction
      //      using CAST will not work with virtual
      //      functions.
      this.CAST("ExampleClass1").pulicVirtualFunction(5);
      //   Instead we have to use 'SR'
      this.SR("ExampleClass1", "pulicVirtualFunction", 5);

      //   The following would call
      //      ExampleClass2::pulicVirtualFunction
      this.SR("ExampleClass2", "pulicVirtualFunction", 5);

      //   The following is equivalent to the above because 'null'
      //      automatically resolves to the parent of the instance's
      //      class, which in the case of 'this' is ExampleClass2.
      this.SR(null, "pulicVirtualFunction", 5);

      //   Trying to call ExampleClass1::pulicFunction using the following
      //      will not work because of name hiding caused by the existance
      //      of ExampleClass2::pulicFunction
      this.pulicFunction(5);
      //   Instead we have to use 'SR'
      this.SR("ExampleClass1", "pulicFunction", 5);

      //   The same problem exists for ExampleClass1::publicVar, and hence the
      //      the following will not work, reading and writing to
      //      ExampleClass2::publicVar instead.
      console.log(this.publicVar);
      this.publicVar = "FIRST CHANGE";
      //   Instead we have to use 'SR'
      console.log(this.SR("ExampleClass1", "publicVar"));
      this.SR("ExampleClass1", "publicVar", "SECOND CHANGE");

      //   Printing the result of the above
      console.log("------------------");
      console.log(this.publicVar);
      console.log(this.SR("ExampleClass2", "publicVar"));
      console.log(this.SR("ExampleClass1", "publicVar"));
   }
});

var instance = crx_new("ExampleClass3");

instance.test();

//SR is also available on the instance
console.log("------------------");
instance.SR("ExampleClass1", "pulicVirtualFunction", 5);
I am ExampleClass3
I am ExampleClass1
I am ExampleClass2
I am ExampleClass2
From ExampleClass2::publicFunction: I am ExampleClass2
From ExampleClass1::publicFunction: I am ExampleClass1
I am ExampleClass3
I am ExampleClass1
------------------
FIRST CHANGE
I am ExampleClass2
SECOND CHANGE
------------------
SECOND CHANGE