There are three types of class functions. In this section we discuss the second type, which are non static virtual functions.
crx_registerClass("ExampleClass",
{
PUBLIC:
{
VIRTUAL:
{
FUNCTIONS:
{
publicVirtualFunction1: function()
{
console.log("publicVirtualFunction1");
},
publicVirtualFunction2: function()
{
console.log("publicVirtualFunction2");
},
publicPureVirtualFunction1: 0
},
FINAL:
{
FUNCTIONS:
{
publicVirtualFinalFunction1: function()
{
console.log("publicVirtualFinalFunction1");
},
publicVirtualFinalFunction2: function()
{
console.log("publicVirtualFinalFunction2");
}
}
}
}
},
PROTECTED:
{
VIRTUAL:
{
FUNCTIONS:
{
protectedVirtualFunction1: function()
{
console.log("protectedVirtualFunction1");
},
protectedVirtualFunction2: function()
{
console.log("protectedVirtualFunction2");
},
protectedPureVirtualFunction1: 0
},
FINAL:
{
FUNCTIONS:
{
protectedVirtualFinalFunction1: function()
{
console.log("protectedVirtualFinalFunction1");
},
protectedVirtualFunction4: function()
{
console.log("protectedVirtualFunction4");
}
}
}
}
},
PRIVATE:
{
VARS:
{
"privateVar": "ExampleClass::privateVar"
},
VIRTUAL:
{
FUNCTIONS:
{
privateVirtualFunction1: function()
{
console.log("privateVirtualFunction1");
},
privateVirtualFunction2: function()
{
console.log("privateVirtualFunction2");
},
privatePureVirtualFunction1: 0
}
}
}
});
crx_registerClass("ExampleSubClass",
{
EXTENDS: "ExampleClass",
PUBLIC:
{
VIRTUAL:
{
FUNCTIONS:
{
publicPureVirtualFunction1: function()
{
console.log("ExampleSubClass::publicPureVirtualFunction1");
}
}
}
},
PROTECTED:
{
VIRTUAL:
{
FUNCTIONS:
{
protectedPureVirtualFunction1: function()
{
console.log("ExampleSubClass::protectedPureVirtualFunction1");
}
}
}
},
PRIVATE:
{
VIRTUAL:
{
FUNCTIONS:
{
privatePureVirtualFunction1: function()
{
console.log("ExampleSubClass::privatePureVirtualFunction1");
}
}
}
}
});
// The following would cause CrxOop to halt, because ExampleClass contains pure
// virtual functions, and thus can not be instatiated. This makes it an
// abstract class.
//var gExampleClass = crx_new("ExampleClass");
// The following would work because ExampleSubClass implements all the pure virtual
// functions found in ExampleClass. If it did not, this would also make it
// an abstract class.
var gExampleSubClass = crx_new("ExampleSubClass");
crx_registerClass("ExampleClass",
{
"VERBOSE": 1,
"public virtual function publicVirtualFunction1": function()
{
console.log("publicVirtualFunction1");
},
"public virtual function publicVirtualFunction2": function()
{
console.log("publicVirtualFunction2");
},
"public virtual function publicPureVirtualFunction1": 0,
"public virtual final function publicVirtualFinalFunction1": function()
{
console.log("publicVirtualFinalFunction1");
},
"public virtual final function publicVirtualFinalFunction2": function()
{
console.log("publicVirtualFinalFunction2");
},
"protected virtual function protectedVirtualFunction1": function()
{
console.log("protectedVirtualFunction1");
},
"protected virtual function protectedVirtualFunction2": function()
{
console.log("protectedVirtualFunction2");
},
"protected virtual function protectedPureVirtualFunction1": 0,
"protected virtual final function protectedVirtualFinalFunction1": function()
{
console.log("protectedVirtualFinalFunction1");
},
"protected virtual final function protectedVirtualFunction4": function()
{
console.log("protectedVirtualFunction4");
},
"private virtual function privateVirtualFunction1": function()
{
console.log("privateVirtualFunction1");
},
"private virtual function privateVirtualFunction2": function()
{
console.log("privateVirtualFunction2");
},
"private virtual function privatePureVirtualFunction1": 0
});
crx_registerClass("ExampleSubClass",
{
VERBOSE: 1,
EXTENDS: "ExampleClass",
"public virtual function publicPureVirtualFunction1": function()
{
console.log("ExampleSubClass::publicPureVirtualFunction1");
},
"protected virtual function protectedPureVirtualFunction1": function()
{
console.log("ExampleSubClass::protectedPureVirtualFunction1");
},
"private virtual function privatePureVirtualFunction1": function()
{
console.log("ExampleSubClass::privatePureVirtualFunction1");
}
});
// The following would cause CrxOop to halt, because ExampleClass contains pure
// virtual functions, and thus can not be instatiated. This makes it an
// abstract class.
//var gExampleClass = crx_new("ExampleClass");
// The following would work because ExampleSubClass implements all the pure virtual
// functions found in ExampleClass. If it did not, this would also make it
// an abstract class.
var gExampleSubClass = crx_new("ExampleSubClass");
publicVirtualFinalFunction1(), publicVirtualFinalFunction2(), protectedVirtualFinalFunction1(), and protectedVirtualFinalFunction2() above are final functions; they can not be overriden in sub classes.
Virtual final functions can not be private.
publicPureVirtualFunction1(), protectedPureVirtualFunction1() and privatePureVirtualFunction1() are pure virtual functions. Classes containing pure virtual functions are Abstract Classes, and can not be instantiated. Classes extending Abstract Classess without fully implementing their pure virtual functions are also Abstract Classes.
Pure virtual functions can not be final.
If you are not familiar with C++, or the concept of virtual functions, refering to the section on class extension might help.
It is important to note, as an example, that like C++, if a derived class was to declate a virtual function f() as private, where it was declared as public in the base class, one could still gain access to f() by casting the instance to the base class. If you are not familiar with C++, an internet search for C++, virtual functions, and the Liskov substitution principle should help.
To understand how to access class private and protected instance virtual functions across class instances refer to the section about 'O'.
See also the section about non static non virtual functions