2015-04-24 15 views
11

Sto cercando di cogliere OOP con JavaScript con esempi molto semplici.Esempio di prototipo ed ereditarietà JavaScript per animali

Il mio obiettivo è creare una gerarchia di classi con Animali come esempio.

In una gerarchia animale semplificato potremmo vedere qualcosa di simile:

  Animal 
      /\ 
    Mammal  Reptile 
     /\   /\ 
    Human Dog Snake Alligator 

voglio prendere questo esempio e creare classi all'interno di JavaScript. Ecco il mio tentativo. Cosa posso fare per migliorarlo?

function Animal(name) { 
    this.name = name; 
    } 

function Mammal() { 
    this.hasHair = true; 
    this.numEyes = 2; 
    this.blood = "warm"; 
} 

function Dog(breed) { 
    this.breed = breed; 
    this.numLegs = 4; 
} 

Dog.prototype = new Animal("Fido"); 
Dog.prototype = new Mammal(); 

var Fido = new Dog("Lab"); 

console.log(Fido.name); // returns undefined when i want it to return Fido 
console.log(Fido.hasHair); // returns true as expected 
console.log(Fido.breed); // returns lab as expected 

Quello che vorrei fare è di avere cane estendere le proprietà di mammiferi e degli animali dal momento che è al tempo stesso, ma non funziona correttamente. Sto assumendo perché sto chiamando dog.prototype = new Mammal() dopo new Animal() che sta sovrascrivendo la connessione.

Come scrivere correttamente queste classi in modo da poter richiamare tutte le proprietà delle loro classi padre?

Grazie.

+0

E 'questo più o meno quello che vuoi? http://jsfiddle.net/294d88su/ – aroth

risposta

7

Si desidera utilizzare Prototypical Inheritance, che in Javascript è un po 'strano ma potente.

function Animal(name) { 
    this.name = name; 
} 

// Example method on the Animal object 
Animal.prototype.getName = function() { 
    return this.name; 
} 

function Mammal(name, hasHair) { 
    // Use the parent constructor and set the correct `this` 
    Animal.call(this, name); 

    this.hasHair = hasHair; 
} 

// Inherit the Animal prototype 
Mammal.prototype = Object.create(Animal.prototype); 

// Set the Mammal constructor to 'Mammal' 
Mammal.prototype.constructor = Mammal; 

Mammal.prototype.getHasHair = function() { 
    return this.hasHair; 
} 

function Dog(name, breed) { 
    // Use the parent constructor and set the correct `this` 
    // Assume the dog has hair 
    Mammal.call(this, name, true); 

    this.breed = breed; 
} 

// Inherit the Mammal prototype 
Dog.prototype = Object.create(Mammal.prototype); 

// Set the Dog constructor to 'Dog' 
Dog.prototype.constructor = Dog; 

Dog.prototype.getBreed = function() { 
    return this.breed; 
} 

var fido = new Dog('Fido', 'Lab'); 

fido.getName(); // 'Fido' 
fido.getHasHair(); // true 
fido.getBreed(); // 'Lab' 

una buona risorsa per OOP in Javascript possono essere trovati sul Mozilla Developer Network

+0

Questo è fantastico! I commenti rendono facile da seguire. Ho alcune domande di follow-up: "Mammal.prototype = Object.create (Animal.prototype);" è lo stesso di "Mammal.prototype = new Animal()"? Dalla mia conoscenza di base hai creato la classe Animal senza un metodo e creato Animal.prototype.getName separatamente. Questa è considerata una "buona pratica" perché non "inquina" la classe genitore con i metodi che ha bisogno di creare ogni volta che viene creato un nuovo animale? È corretto? Tutto quello che capisco è che si tratta di "buone pratiche", e non capisco perché sia ​​esattamente così. Grazie. – sjmartin

+1

L'uso di Object.create è preferito perché crea un oggetto basato sul prototipo fornito senza chiamare il costruttore Animal. Quando definisci l'ereditarietà, Mammal e Dog non hanno un nome da passare al costruttore di Animal. Chiamare il costruttore genitore all'interno del costruttore come ho fatto consente di passare i parametri. E tu hai ragione. Se si impostano i metodi sulla classe Animal anziché sul suo prototipo, viene creata una nuova copia di tale funzione per ogni istanza. Se invece è sul prototipo, l'animale non avrà una copia del metodo, ma saprà controllare il prototipo. – DevShep

Problemi correlati