当且仅当父类具有该函数时才调用super

时间:2014-06-23 23:28:52

标签: inheritance coffeescript

通常在Coffeescript中,如果我想调用父类中存在的函数,我只是在最后调用super。 e.g。

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

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

onShow: ->
  // do things
  super

这生成了以下形式的Javascript:

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

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

  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中有助记符可以做我在这里尝试的事吗?

2 个答案:

答案 0 :(得分:3)

是的, super ,答案不是,但不管怎样,让我们​​潜入......

当我们知道我们有super

首先,让我们看看标准情况,我们有一个类 Animal ,具有speak函数。我们还有一个 Bird ,它扩展了 Animal 并拥有自己的speak函数,该函数调用super版本来自 Animal

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);

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

tapeSlippedOff = Math.random() > 0.5
if (tapeSlippedOff)
  MuteAnimal::speak = Animal::speak

new BeakTapedShutBird('Geoff').speak()

答案 1 :(得分:-1)

根据{{​​3}},

超级是一个保留字。