2012-01-30 3 views
16
coffeescript

The documentation expliquer comment étendre une classeextension des classes multiples dans

class Zebra extends Animal 
    ... 

Mais comment puis-je prolonger plusieurs classes? Ce qui suit ne pas travail

class Sidebar extends Controller, EventEmitter 
    ... 

Mais je voudrais qu'il a fait. Le JavaScript derrière cela est plus que capable d'étendre un nombre quelconque de classes en utilisant la fonction __extend, mais y a-t-il un moyen de le faire en café-script?

+0

vous pouvez jeter un oeil à cette discussion: https://github.com/ jashkenas/coffee-script/issues/452 – qiao

+0

suds ... Ça ne me dit rien de bon – Hubro

+0

JavaScript utilise l'héritage du prototype ... Derrière la scène, extends utilise la propriété 'prototype' pour créer une chaîne ... peut avoir "hérite" f rer plusieurs objets uniquement si les objets sont une chaîne prototype ... p. ex. Zèbre pourrait étendre végétarienAnimal et végétarienAnimaux étend Animal. – Jaider

Répondre

37

Devinez Je vais juste répondre à ma propre question. La façon dont j'ai fini par gérer ceci est d'étendre toutes mes classes d'une classe que j'appelle "SuperClasse" (le nom n'a pas d'importance). De cette classe je peux étendre n'importe quel nombre de classes. Quoi qu'il en soit la classe ressemble à ceci

moduleKeywords = ['included', 'extended'] 

class SuperClass 
    @include: (obj) -> 
     throw('include(obj) requires obj') unless obj 
     for key, value of obj.prototype when key not in moduleKeywords 
      @::[key] = value 

     included = obj.included 
     included.apply(this) if included 
     @ 

Quasiment juste volé de Spine. Un exemple d'une classe étendue de SuperClass:

class Sidebar extends SuperClass 

    # Include some other classes 
    @include Controller 
    @include EventEmitter 

    ### 
    Constructor function 
    ### 
    constructor: -> 
     # Call extended constructors 
     Controller.call @ 
     EventEmitter.call @ 

     console.log 'Sidebar instantiated' 

Notez que pour appeler le constructeur de la classe héritée de la fonction de la classe est appelée avec @/this comme contexte. Je ne l'ai pas eu besoin d'étendre encore, mais j'imagine que c'est très semblable fonctions de classe pour appeler le constructeur parent:

someFunction: -> 
    ExtendedClass::someFunction.call @ 

S'il vous plaît modifier ce poste si je me trompe. Aussi s'il vous plaît excuser mon manque de terminologie de l'héritage de classe - Je ne suis pas expert


Mise à jour: On peut également définir un constructeur de superclasse appelée automatiquement le constructeur pour toutes les classes incluses sur instanciation. De cette façon, vous devrez juste appeler super() de la sous-classe. Je ne ai pas dérangé avec cela si

+0

Je pense que l'appel super() ne fonctionnera pas.Vous auriez besoin d'une sorte de tableau stockant la classe d'un objet 'include @. Ce qui ne fonctionnerait pas parce que vous devez réinitialiser cette même variable à '[]'. – Atmocreations

6

Ceci est dénommé mixin. CoffeeScript ne les inclura jamais nativement comme vous pouvez le lire dans la section Classes sur the CoffeeScript FAQ. Mais il existe différentes implémentations là-bas, in this Gist, dans le Little Book, et this one pour JS semble aussi fonctionner avec CoffeeScript Classes.

2

Vous pouvez utiliser un petit assistant, qui crée une chaîne prototype appropriée avec l'appel correct super. classes existantes dans la chaîne respectées, utilise les leurs "projections"

https://gist.github.com/darrrk/75d6a6a4d431e7182888

virtual_class = (classes...)-> 
    classes.reduceRight (Parent, Child)-> 
    class Child_Projection extends Parent 
     constructor: -> 
     # Temporary replace Child.__super__ and call original `constructor` 
     child_super = Child.__super__ 
     Child.__super__ = Child_Projection.__super__ 
     Child.apply @, arguments 
     Child.__super__ = child_super 

     # If Child.__super__ not exists, manually call parent `constructor` 
     unless child_super? 
      super 

    # Mixin prototype properties, except `constructor` 
    for own key of Child:: 
     if Child::[key] isnt Child 
     Child_Projection::[key] = Child::[key] 

    # Mixin static properties, except `__super__` 
    for own key of Child 
     if Child[key] isnt Object.getPrototypeOf(Child::) 
     Child_Projection[key] = Child[key] 

    Child_Projection 

Exemple:

class My extends virtual_class A, B, C 
Questions connexes