【问题标题】:How can I apply the decorator pattern with CoffeeScript to extend an object?如何使用 CoffeeScript 应用装饰器模式来扩展对象?
【发布时间】:2016-04-16 03:37:09
【问题描述】:

我正在尝试创建一个将与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: 等于所有这些。因此,如果有人有任何建议或提示,我将不胜感激。

谢谢!

【问题讨论】:

  • 到底是什么问题?

标签: node.js coffeescript decorator


【解决方案1】:

你的问题是这样的:@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

【讨论】:

  • 循环的目的是最终在调用超类的函数之前做一些逻辑
  • 那么只需在子类上声明函数并在调用super之前完成工作。更新答案举个例子。
  • 但我不想每次通话都这样做。我在调用超类之前所做的事情在所有情况下都是一样的
  • 您应该只需要声明一次“作品”。如果这是您想在构造函数中执行的工作(当您调用 new 时会发生什么,然后在构造函数中编写该代码然后调用 super。如果它们是在调用实例方法之前发生的特定工作主体,那么按照上面的gists 示例进行操作。但是,我对您的示例的阅读告诉我,您可能对原型继承的工作方式有一些误解。
猜你喜欢
  • 2018-09-21
  • 2013-02-19
  • 1970-01-01
  • 2021-08-16
  • 2016-08-18
  • 2021-03-28
  • 1970-01-01
  • 1970-01-01
  • 2021-07-07
相关资源
最近更新 更多