Ereditarietà vs mixin in lingue dinamiche?

18

Quando preferisci i pattern di ereditarietà dei mix in lingue dinamiche?

Con mixin intendo l'effettivo mixaggio corretto, come nell'inserimento di funzioni e membri dati in un oggetto in runtime.

Quando useresti, ad esempio, l'ereditarietà prototipale invece dei mixin? Per illustrare più chiaramente cosa intendo per mixin, alcuni pseudocodici:

asCircle(obj) {
  obj.radius = 0
  obj.area = function() {
    return this.radius * this.radius * 3.14
  }

myObject = {}
asCircle(myObject)
myObject.area() // -> 0
    
posta Magnus Wolffelt 05.12.2011 - 14:24
fonte

4 risposte

14

L'eredità prototipica è semplice. Ha un unico vantaggio rispetto ai mixin.

Questo è che è un collegamento live. se cambi il prototipo, tutto ciò che eredita è cambiato.

Esempio utilizzando pd

var Circle = {
  constructor: function _constructor() {
    this.radius = 0;
    return this;
  },
  area: function _area() {
    return this.radius * this.radius * Circle.PI
  },
  PI: 3.14
};

var mixedIn = pd.extend({}, Circle).constructor();
var inherited = pd.make(Circle, {}).constructor();

Circle.perimeter = perimeter;

inherited.perimeter(); // wins
mixedIn.perimeter(); // fails

function perimeter() {
  return 2 * this.radius;
}

Quindi in sostanza, se vuoi che le modifiche al cerchio "interfaccia" riflettano in fase di esecuzione su tutti gli oggetti che "utilizzano" la sua funzionalità, quindi ereditali da esso.

Se non vuoi che le modifiche riflettano, configuralo.

Nota che i mixin hanno anche più scopo. I mixin sono il tuo meccanismo per "ereditarietà" multipla.

Se vuoi che un oggetto implementi più "interfacce", allora sarà in cui dovrai mescolare un po '. Quello che usi per l'ereditarietà prototipica è quello che vuoi che le modifiche riflettano in fase di esecuzione , gli altri verranno mixati.

    
risposta data 05.12.2011 - 15:06
fonte
11

Il senso del cavallo mi dice questo:

  • Se qualcosa è utile across più oggetti o gerarchie di classi - rendilo un mixin
  • Se qualcosa è solo utile lungo una singola gerarchia - usa l'ereditarietà

Note correlate:

  • La parola "utile" dovrebbe essere presa metaforicamente
  • Per quei linguaggi che non hanno ereditarietà multiple, i mixin sono una buona alternativa
  • PHP 5.4 introduce i tratti che hanno bontà da entrambi i mix e mondi di eredità multipli
risposta data 05.12.2011 - 15:04
fonte
8

Utilizza il test "Is-a".

L'ereditarietà è limitata al caso in cui è possibile pronunciare "Sottoclasse IS A Superclass". Sono lo stesso tipo di cosa. "Il formaggio è un prodotto lattiero-caseario".

I mixin sono per tutto altro. "Il formaggio può essere usato in un sandwich". Il formaggio non è un panino, ma partecipa al sandwich.

PS. Questo non ha nulla a che fare con i linguaggi dinamici. Qualsiasi linguaggio di ereditarietà multipla con compilazione statica (ad es., C ++) ha lo stesso punto di decisione.

    
risposta data 05.12.2011 - 18:08
fonte
0

Bene, il miglior esempio che posso darti è un attore per un gioco che ha ereditarietà per alcune cose di base ma usa mixins / plugins per funzionalità condivise. La funzionalità condivisa potrebbe essere (direttamente dal codice sorgente!):

var plugins = {
    SingleVisualEntity : SingleVisualEntity,
    JumpBehaviour      : JumpBehaviour,
    WeaponBehaviour    : WeaponBehaviour,
    RadarBehaviour     : RadarBehaviour,
    EnergyGatherer     : EnergyGatherer,
    LifeBarPlugin      : LifeBarPlugin,
    SelectionPlugin    : SelectionPlugin,
    UpgradePlugin      : UpgradePlugin,
    BrainPlugin        : BrainPlugin,
    PlanetObjectPlugin : PlanetObjectPlugin,
}
    
risposta data 29.01.2014 - 00:16
fonte

Leggi altre domande sui tag