在咖啡脚本中扩展多个类

发布于 2024-12-31 20:56:39 字数 343 浏览 1 评论 0原文

文档解释了如何扩展一个类

class Zebra extends Animal
    ...

但是如何扩展多个类呢?以下内容不起作用

class Sidebar extends Controller, EventEmitter
    ...

,但我希望它起作用。这背后的 JavaScript 不仅能够使用 __extend 函数扩展任意数量的类,但是有没有办法在咖啡脚本中做到这一点?

The documentation explain how to extend a class

class Zebra extends Animal
    ...

But how do I extend multiple classes? The following does not work

class Sidebar extends Controller, EventEmitter
    ...

But I wish it did. The JavaScript behind this is more than able to extend any number of classes using the __extend function, but is there a way to do it in coffee-script?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

伪装你 2025-01-07 20:56:39

我想我只会回答我自己的问题。我最终处理这个问题的方法是从我称为“SuperClass”的类(名称并不重要)扩展所有类。从该课程中我可以扩展任意数量的课程。无论如何,这个类看起来像这样,

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
        @

几乎只是从 Spine 偷来的。从 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'

请注意,要调用继承类的构造函数,将使用 @/this 作为上下文来调用类函数。我还不需要扩展类函数,但我想这与调用父构造函数非常相似:

someFunction: ->
    ExtendedClass::someFunction.call @

如果我错了,请编辑这篇文章。另外请原谅我缺乏类继承术语 - 我不是专家


更新:还可以为 SuperClass 定义一个构造函数,它在实例化时自动调用所有包含的类的构造函数。这样你只需要从子类调用 super() 。不过我并没有为此烦恼

Guess I'll just answer my own question. The way I ended up handling this is extending all my classes from a class I call "SuperClass" (the name doesn't matter). From that class I can extend any number of classes. Anyway the class looks like this

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
        @

Pretty much just stole it from Spine. An example of a class extended from 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'

Notice that to call the inherited class' constructor the class function is called with @/this as context. I haven't needed to extend class functions yet, but I imagine it's very similar to calling the parent constructor:

someFunction: ->
    ExtendedClass::someFunction.call @

Please edit this post if I'm wrong. Also please excuse my lack of class inheritance terminology - I'm no expert


Update: One could also define a constructor for SuperClass that automatically called the constructor for all included classes on instantiation. That way you'd just need to call super() from the subclass. I haven't bothered with that though

骑趴 2025-01-07 20:56:39

这称为 mixin。 CoffeeScript 永远不会在本地包含它们,您可以在 CoffeeScript FAQ 的类部分中阅读。但是有各种实现,在这个要点中,在小书,以及 这本 JS 似乎可以与 CoffeeScript 类一起使用还。

This is referred to as a mixin. CoffeeScript will never include them natively as you can read in the Classes section on the CoffeeScript FAQ. But there are various implementations out there, in this Gist, in the Little Book, and this one for JS seems to work with CoffeeScript Classes also.

焚却相思 2025-01-07 20:56:39

您可以使用小助手,它通过正确的调用 super 创建正确的原型链。
链中的现有类没有违反,使用他们的“投影”

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

class My extends virtual_class A, B, C

You can use little helper, which create proper prototype chain with correct call super.
Existing classes in chain not violated, uses theirs "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

Example:

class My extends virtual_class A, B, C
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文