【问题标题】:Calling super if and only if the parent class has the function当且仅当父类具有该功能时才调用 super
【发布时间】:2014-08-14 02:20:49
【问题描述】:

通常在Coffeescript中,如果我想调用一个存在于父类中的函数,我只是在最后抛出一个对super的调用。例如

initialize: (options) ->
  // do some stuff here
  super options

我正在使用一个框架,该框架具有一些函数,如果它们被定义,则会被调用,例如 onShowonClose。在许多类中,这些功能不存在,但可能会在以后的开发中添加。通常,我会定义一个扩展另一个类的类,并出于习惯在我的onShow 方法中调用super

onShow: ->
  // do things
  super

这生成的 Javascript 格式为:

 return ClassName.__super__.onShow.apply(this, arguments);

不幸的是,这假定onShow 存在于父类中,但它可能不存在。通常,我可以通过生成 Javascript 的 funcName?() 来解决可能存在的函数:

  if (typeof funcName === "function") {
    funcName();
  }

但是super?() 没有按预期工作,生成了这个 Javascript:

return typeof (_base = ClassName.__super__.onClose.apply(this, arguments)) === "function" ? _base() : void 0;

当我期望时,改为:

return typeof (_base = ClassName.__super__.onClose) === "function" ? _base.apply(this, arguments) : void 0;

显然,我可以手动删除对super 的调用,但我想让我的子类在以后更改父类时自动继承父类行为。

Coffeescript 中是否有助记符来执行我在这里尝试的操作?

【问题讨论】:

    标签: inheritance coffeescript


    【解决方案1】:

    【讨论】:

      【解决方案2】:

      是的,super,答案不是,但无论如何让我们潜入...

      当我们知道我们有 super:

      首先,让我们看看标准情况,我们有一个类 Animal,带有一个 speak 函数。我们还有一个 Bird 扩展了 Animal 并拥有自己的 speak 函数,它从 Animalsuper 版本/strong>。

      class Animal
        constructor: (@name, @sound = 'AAAARGH!') ->
        speak: -> alert "My name is #{@name}, #{@sound}"
      
      class Bird extends Animal
        constructor: (@name) ->
          super @name, 'CA-CAW!'
        speak: ->
          alert 'I\'m a bird!'
          super
      

      当按如下方式使用时,这当然可以按预期工作:

      new Bird('Harry').speak()
      

      当我们查看生成的 JavaScript 时,这是有道理的:

      Bird = (function(_super) {
        __extends(Bird, _super);
      
        function Bird(name) ...
      
        Bird.prototype.speak = function() {
          alert('I\'m a bird!');
          return Bird.__super__.speak.apply(this, arguments);
        };
      
        return Bird;
      
      })(Animal);
      

      这个生成的 JS 还向我们展示了我们可以通过两种方式从该类的方法访问该类的超类:

      • _super
      • Class.__super__

      这些都不是真正的选择,但如果你绝望的话,它们会起作用......

      当我们不知道是否有super:

      class MuteAnimal
        constructor: (@name, @sound = '') ->
      
      class BeakTapedShutBird extends MuteAnimal
        constructor: (@name) ->
          super @name, 'HELP!!!'
        speak: ->
          alert '**muffled noise**'
          # could also be @__super__::speak?, pick your poison:
          if _super::speak? then super 
      

      生成的 JS 将尊重我们对_super 的引用,因此我们得到以下内容:

      BeakTapedShutBird = (function(_super) {
        __extends(BeakTapedShutBird, _super);
      
        function BeakTapedShutBird(name) ...
      
        BeakTapedShutBird.prototype.speak = function() {
          if (_super.prototype.speak != null) {
            return BeakTapedShutBird.__super__.speak.apply(this, arguments);
          }
        };
        return BeakTapedShutBird;
      })(MuteAnimal);
      

      这不是很好,也不是惯用的,但至少这意味着如果 super 函数不存在,我们就不会得到 error

      tapeSlippedOff = Math.random() > 0.5
      if (tapeSlippedOff)
        MuteAnimal::speak = Animal::speak
      
      new BeakTapedShutBird('Geoff').speak()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-07-10
        • 1970-01-01
        • 1970-01-01
        • 2013-10-30
        • 1970-01-01
        • 2021-06-08
        • 1970-01-01
        相关资源
        最近更新 更多