如何使用CoffeeScript应用装饰器模式来扩展对象?

时间:2014-05-28 13:29:29

标签: node.js coffeescript decorator

我正在尝试创建一个与github API交互的节点模块,但会将结果缓存在redis中。您可以在https://github.com/shamoons/github-redis-etag关注我的进度(拜托我吧!)。作为基础,我正在使用mikedeboer的github package

我想要做的是创建一个扩展GitHubApi模块功能的类,并在调用Github调用之前调用一些redis魔法。到目前为止我所拥有的是:

_ = require 'lodash'
base91 = require 'base91'
GitHubApi = require 'github'
redis = require 'redis'
util = require 'util'

class GitHubETag extends GitHubApi
  repos = {}

  constructor: (defaults = {}) ->
    @github = new GitHubApi
      version: '3.0.0' || defaults.version?
      debug: false || defaults.false?
      protocol: 'http' || defaults.protocol?
      host: null || defaults.host?
      pathPrefix: '' || defaults.pathPrefix?
      timeout: null || defaults.timeout?

    @redisClient = redis.createClient ('6379' || defaults.redis?.port?), ('127.0.0.1' || defaults.redis?.host?)

    githubObjects = ['events', 'gists', 'gitdata', 'issues', 'markdown', 'orgs', 'pullRequests', 'repos', 'search', 'statuses', 'user']

    _.each githubObjects, (object) =>
      @object = {}

      _.each _.keys(@github[object]), (key) =>
        fn = @github[object][key]
        @object[key] = @github[object][key]
        console.log "#{object}:#{key}"
我意识到这是各种各样的错误。为了实例化,我正在做:

github = new GitHubETag
  version: '3.0.0'
  redis:
    port: '6379'
    host: '127.0.0.1'

console.log github

这也是错误的,因为这会返回与GitHubApi相同的对象,除非github:等于所有这些。所以如果有人有任何建议或提示,我会非常感激。

谢谢!

1 个答案:

答案 0 :(得分:3)

你的问题是:@github = new GitHubApi(args...)

你不必在构造函数内部使用父类调用new,它会破坏目的。并且因为你的构造函数是你的类体中唯一的方法,所以当你在子类上调用new时,它们都会被返回。您还可以为默认参数重写构造函数,如下所示。

class GitHubETag extends GitHubApi
  repos = {}

  constructor: ({@version, @debug}) ->
    @version ?= '3.0.0'
    @debug ?= false
    etc..


instance = new GitHubETag(version: '2.0.0')
instance.version #=> '2.0.0'
instance.debug #=> false

我不确定在构造函数底部使用每个循环所以我无法在那里做出评论,但是如果你只是想在实例上动态设置方法,那么你不必,因为你扩展超类。如果你不需要任何子类方差那些方法,它们已经定义。例如,使用上面的代码,您应该能够:

instance.events #=> function
superclass = new GitHubApi()
instance.events == superclass.events #=> true

覆盖,或在父类方法之前工作,定义方法,完成工作然后调用super:

class GitHubETag extends GitHubApi
  gists: ()->
    console.log "doing work"
    super

instance.gists() #=> logs and calls through