2012-01-30 15 views
16

The documentation explicar cómo extender una claseLa extensión de múltiples clases en coffeescript

class Zebra extends Animal 
    ... 

Pero ¿cómo extender múltiples clases? A continuación se hace no trabajo

class Sidebar extends Controller, EventEmitter 
    ... 

Pero me gustaría que lo hizo. El JavaScript detrás de esto es más que capaz de extender cualquier cantidad de clases usando la función __extend, pero ¿hay alguna manera de hacerlo en coffee-script?

+0

se puede echar un vistazo a esta discusión: https://github.com/ jashkenas/coffee-script/issues/452 – qiao

+0

espuma ... Eso no es un buen augurio para mí – Hubro

+0

JavaScript usa prototipo de herencia ... Detrás de la escena, extends utiliza la propiedad única 'prototipo' para crear una cadena ... usted puede tener "hereda" f rom múltiples objetos solo si los objetos son una cadena de prototipos ... p. Zebra podría extender VegetarianAnimal y vegetarianAnimal extends Animal. – Jaider

Respuesta

37

Supongo que solo responderé mi propia pregunta. La forma en que terminé manejando esto es extendiendo todas mis clases desde una clase que llamo "SuperClass" (el nombre no importa). De esa clase puedo extender cualquier cantidad de clases. De todos modos la clase tiene este aspecto

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 
     @ 

prácticamente sólo se lo robó a Spine. Un ejemplo de una clase extendida desde 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' 

Tenga en cuenta que para llamar al constructor de la clase heredada la función de clase se llama con @/this como contexto. No he necesitado para ampliar las funciones de clase todavía, pero me imagino que es muy similar a una llamada al constructor padre:

someFunction: -> 
    ExtendedClass::someFunction.call @ 

favor editar este post si estoy equivocado. También pido disculpas por mi falta de terminología de la herencia de clases - No soy un experto


Actualización: También se podría definir un constructor de superclase que llama automáticamente al constructor para todas las clases incluidas en la instanciación. De esta forma, solo necesita llamar al super() desde la subclase. No me he molestado con eso aunque

+0

Creo que llamar a super() no funcionará.Necesitarías algún tipo de arreglo que almacenara la clase de un objeto '@ include'd. Lo cual no funcionaría porque necesita restablecer esta misma variable a '[]'. – Atmocreations

2

Puede usar little helper, que crea una cadena de prototipos adecuada con la llamada correcta super. clases existentes en la cadena no violados, utiliza el suyo "proyecciones"

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 

Ejemplo:

class My extends virtual_class A, B, C 
Cuestiones relacionadas