Overriding Properties

Core.extend() provides the developer to control which properties (methods and variables) of a class may be overridden by subclasses, and which may not. By default, all declared properties are final, that is, they may not be overridden by subclasses. There are a few exceptions to this rule, notably that constructors may always be overridden, as may the toString() and valueOf() methods.

To allow properties to be overridden, they must be declared in a $virtual block. The following syntax is used:

OverrideExample = Core.extend({

    $virtual: {

        virtualVariable: "You can override this!",

        virtualMethod: function() {
            return "I can be overridden!"; 
        }
    },

    finalMethod: function() {
        return "I can NOT be overriddden!";
    },

    finalVariable: "Don't even *think* about overriding this!"
});

The following invocation of Core.extend() will execute successfully:

DeriveSuccessExample = Core.extend(OverrideExample, {

    virtualVariable: "This variable overrides one in the base class.",

    virtualMethod: "This method overrides one in the base class."
});

The following two invocations of Core.extend() will fail, throwing an exception:

DeriveFailExample1 = Core.extend(OverrideExample, {

    finalVariable: "I think I'll try and override a final variable."
});
DeriveFailExample2 = Core.extend(OverrideExample, {

    finalMethod: function() {
        return "I decided not to read to the documentation.";
    }
});

Invoking Super-Methods

Function.call(), first mentioned in the Inheritance chapter with regard to invoking super-constructors, can in fact be used to invoke any overridden method. To do so, we invoke call() on the appropriate method of the prototype of our base class. As was done in the case of invoking the super-constructor, the first parameter specifies the value of the this-pointer that will be used when the method is executed, and any additional parameters are passed as arguments to the method.

SuperMethodExample = Core.extend(OverrideExample, {

    virtualMethod: function() {
        var superResult = OverrideExample.prototype.virtualMethod.call(this);
        return "I called the super method: " + superResult;
    }
});