Override (Sobrescribir métodos y atributos).
Al heredar los métodos y atributos públicos de la superclase, es posible sobrescribir estos y tener acceso a los métodos y atributos sobrescritos de la superclase, para poder acceder a estos utilizaremos la palabra reservada $$super.
function ClassA(){
var message = "ClassA";
this.getMessage = function(){
return message;
};
this.setMessage = function(msg){
message = msg;
};
// constructor de la clase
this.$$constructor = function(msg){
message = msg || message;
};
};
var ClassA = Class.create("ClassA",ClassA);
function ClassB(){
var message = "ClassB";
this.sender = "anonymous";
this.getMessage = function(){
return this.sender + " says " + message + " " + this.$$super[0].getMessage();
};
this.setMessage = function(msg){
message = msg;
};
// constructor de la clase
this.$$constructor = function(nm,msg){
message = msg || message;
this.sender = nm;
};
}
var ClassB = Class.extend("ClassB",ClassA,ClassB);
var peter = new ClassB("Peter", " hello");
alert(peter.getMessage()) // "Peter says hello ClassA"
Como puedes ver $$super es un array, para tener acceso a ClaseA desde ClaseB hemos puesto 0 en el índice de $$super, ya que ClaseA es la clase superior en la jerarquía. Si tenemos una jerarquía de clases mayor y queremos saber en que nivel esta una clase tenemos el método getIndex del objecto Class.
Class.getIndex(ClassA); return 0
Class.getIndex(ClassB); return 1
Una cosa que tenemos que tener en cuenta cuando sobrescribimos un método es si este método utiliza alguna atributo privado.
function ClassA(){
var value = "default A";
this.getValue = function(){
return value + " ["+ this.$$className + "]";
};
this.setValue = function(v){
value = v
};
this.$$constructor = function(v){
this.setValue(v || value);
};
};
var classA = Class.create("ClassA",ClassA);
function ClassB(){
var value = "default B";
this.setValue = function(v){
value = v
};
this.$$constructor = function(v){
this.setValue(v || value);
};
};
var ClassB = Class.extend("ClassB",ClassA,ClassB);
var instB = new ClassB("instance B");
alert(instB.getValue());// default A[ClassB]
Como puedes ver instB.getValue devuelve el valor value de ClassA, esto se debe a que los métodos públicos sólo tienen acceso a los atributos y métodos privados de la clase donde fueron declarados.
Lo que deberemos hacer es sobrescribir el método getValue.
function ClassA(){
var value = "default A";
this.getValue = function(){
return value + " ["+ this.$$className + "]";
};
this.setValue = function(v){
value = v
};
this.$$constructor = function(v){
this.setValue(v || value);
};
};
var classA = Class.create("ClassA",ClassA);
function ClassB(){
var value = "default B";
this.getValue = function(){
return value + " ["+ this.$$className + "]";
};
this.setValue = function(v){
value = v
};
this.$$constructor = function(v){
this.setValue(v || value);
};
};
var ClassB = Class.extend("ClassB",ClassA,ClassB);
var instB = new ClassB("instance B");
alert(instB.getValue());//instance B [ClassB]
Para obtener una clase determinada dentro de una jerarquía podemos hacerlo directamente o mediante $$super.
var ClassA = Class.create("ClassA",function(){
this.getFirstClass = function(){
return Class.getName(ClassA);
};
this.$$constructor = function(){
};
});
var ClassB = Class.extend("ClassB",ClassA,function(){
this.$$constructor = function(){
};
});
var ClassC = Class.extend("ClassB",ClassB,function(){
this.$$constructor = function(){
};
});
var iA = new ClassA();
var iB = new ClassB();
var iC = new ClassC();
alert(iA.getFirstClass() + "\n" + iB.getFirstClass() + "\n" + iC.getFirstClass());
/*
ClassA
ClassA
ClassA
*/
JSimpleClass permite clonar clases, si clonásemos ClassA, el método getFirtClass devolverá "ClassA" tanto en la clase clonada como en la original.
Con $$super no tenemos este problema.
var ClassA = Class.create("ClassA",function(){
this.getFirstClass = function(){
// si $$super existe es que estamos el nivel 1 de la jerarquía
if(this.$$super) return Class.getName(this.$$super[0].$$class);
else return Class.getName(this.$$class);
};
this.$$constructor = function(){
};
});
var CloneClassA = Class.clone("CloneClassA",ClassA);
var ClassB = Class.extend("ClassB",ClassA,function(){
this.$$constructor = function(){
};
});
var ClassC = Class.extend("ClassB",ClassB,function(){
this.$$constructor = function(){
};
});
var iA = new ClassA();
var iB = new ClassB();
var iC = new ClassC();
var cA = new CloneClassA();
alert(iA.getFirstClass() + "\n" + iB.getFirstClass() + "\n" + iC.getFirstClass() + "\n" + cA.getFirstClass());
/*
ClassA
ClassA
ClassA
CloneClassA
*/
Para saber si estamos en la primera clase de la jerarquía, nos servimos de $$super, ya que este atributo no existe en ésta, también podemos utilizar Class.getIndex.
var ClassA = Class.create("ClassA",function(){
this.$$constructor = function(){
};
});
var ClassB = Class.extend("ClassB",ClassA,function(){
this.getSecondClass = function(){
return Class.getIndex(this) == 1 ? this.$$className: this.$$super[1].$$className;
};
this.$$constructor = function(){
};
});
var ClassC = Class.extend("ClassB",ClassB,function(){
this.$$constructor = function(){
};
});
var iB = new ClassB();
var iC = new ClassC();
alert(iB.getSecondClass() + "\n" + iC.getSecondClass());
/*
ClassB
ClassB
*/
Como puedes ver $$super nos proporciona un gran control.