JavaScript: il pattern pseudoclassical

JavaScript: il pattern pseudoclassical

Il pattern pseudoclassical in JavaScript cerca di emulare l'ereditarietà in un modo che assomiglia a quelli usati in Java o C++. Usando questo pattern cerchiamo di ricreare il comportamento delle classi in altri linguaggi specie quando gli oggetti sono istanze di queste classi.

In JavaScript un modo per implementare questo pattern è invocare una funzione costruttore e far puntare la proprietà prototype della classe figlia a quella della classe genitrice.


/**
* Funzione di utility 
**/
var extendObj = function( childObj, parentObj ) { 
	childObj.prototype = parentObj.prototype;
};

// Oggetto base
var Human = function() {};

// Proprietà ereditabili 
Human.prototype = {
	name: "",
	gender: "", 
	planetOfBirth: "Earth", 
	sayGender: function() {
		alert( this.name + " says my gender is " + this.gender ); 
	},
	sayPlanet: function() {
		alert( this.name + " was born on " + this.planetOfBirth );
	} 
};


// Uomo
var Male = function ( name ) { 
	this.gender = "Male";

	this.name = "David"; 
};

// Eredita da Human 
extendObj( Male, Human );

// Donna
var Female = function ( name ) { 
	this.name = name; 
	this.gender = "Female";
};

// Eredita da Human
extendObj( Female, Human );


// Nuove istanze
var david = new Male( "David" ); 
var jane = new Female( "Jane" );

david.sayGender(); // David says my gender is Male 
jane.sayGender(); // Jane says my gender is Female


// Modifico una proprietà nel prototype di Male
Male.prototype.planetOfBirth = "Mars"; 

david.sayPlanet(); // David was born on Mars 
jane.sayPlanet(); // Jane was born on Mars

Come si può notare abbiamo riscontrato un problema: invece del messaggio "Jane was born on Earth" abbiamo lo stesso messaggio restituito dall'altra istanza dell'oggetto che eredita direttamente da Human.

Dato che esiste un collegamento diretto tra le proprietà prototype degli oggetti Human e Male, modificando questa proprietà abbiamo un effetto a cascata su tutti gli oggetti che ereditano dall'oggetto Human perché JavaScript passa gli oggetti per riferimento (reference) non per valore.

Per risolvere il problema dobbiamo usare un oggetto temporaneo di transizione che erediti le sue proprietà da Human aggirando il passaggio per riferimento.

Ecco la nostra funzione di utility modificata:


var extendObj = function( childObj, parentObj ) {
	var tmpObj = function() {};
	tmpObj.prototype = parentObj.prototype;
	childObj.prototype = new tmpObj();
	childObj.prototype.constructor = childObj;
};

L'ultima riga della nostra funzione ha lo scopo di far puntare correttamente il costruttore dell'oggetto che eredita alla funzione relativa.

Torna su