包含模块时使用间接是否有优势(来自 7 周内的 7 种语言,Ruby 第 3 天)

发布于 2024-12-20 18:31:45 字数 1208 浏览 1 评论 0原文

Bruce 在“七周内的七种语言”,Ruby 第 3 天,第 38 页中给出了以下示例:

module ActsAsCsv
  def self.included(base)
    base.extend ClassMethods
  end

  module ClassMethods
    def acts_as_csv
      include InstanceMethods
    end
  end

  module InstanceMethods
    def read
       #fill @csv_contents and @headers from file self.class.to_s.downcase + '.txt'
    end

    attr_accessor :headers, :csv_contents

    def initialize
      read
    end
  end
end

class RubyCsv
  include ActsAsCsv
  acts_as_csv
end

m = RubyCsv.new
puts m.headers.inspect
puts m.csv_contents.inspect

我看不出 def self.included(base)使用间接寻址的任何原因类方法。与简单地包含模块 InstanceMethods 相比,上述代码是否有优势?


详细来说:对于“简单地包含模块 InstanceMethods”,我指的是以下代码:

  module InstanceMethods #defined as above
    def read
       #fill @csv_contents and @headers from file self.class.to_s.downcase + '.txt'
    end

    attr_accessor :headers, :csv_contents

    def initialize
      read
    end    
  end

class RubyCsv
  include InstanceMethods
end

m = RubyCsv.new
puts m.headers.inspect
puts m.csv_contents.inspect

由于鸭子类型,这不是和通过 base.extend ClassMethods 一样好吗?

Bruce gives the following example in "Seven languages in seven weeks", Ruby day 3, page 38:

module ActsAsCsv
  def self.included(base)
    base.extend ClassMethods
  end

  module ClassMethods
    def acts_as_csv
      include InstanceMethods
    end
  end

  module InstanceMethods
    def read
       #fill @csv_contents and @headers from file self.class.to_s.downcase + '.txt'
    end

    attr_accessor :headers, :csv_contents

    def initialize
      read
    end
  end
end

class RubyCsv
  include ActsAsCsv
  acts_as_csv
end

m = RubyCsv.new
puts m.headers.inspect
puts m.csv_contents.inspect

I do not see any reason for the indirection used by def self.included(base) and ClassMethods. Is there an advantage of the above code over simply including the module InstanceMethods?


In detail: With "simply including the module InstanceMethods" I mean the following code:

  module InstanceMethods #defined as above
    def read
       #fill @csv_contents and @headers from file self.class.to_s.downcase + '.txt'
    end

    attr_accessor :headers, :csv_contents

    def initialize
      read
    end    
  end

class RubyCsv
  include InstanceMethods
end

m = RubyCsv.new
puts m.headers.inspect
puts m.csv_contents.inspect

Because of duck typing, isn't this just as good as going via base.extend ClassMethods?

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

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

发布评论

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

评论(2

眼趣 2024-12-27 18:31:45

原始代码允许您执行此操作:

class A
  include ActsAsCsv
end

class B < A
  acts_as_csv
end

则会更干净

  • 虽然在这种情况下使用继承更多是一种品味问题,但如果添加与 Aacts_as_csv 以外的更多方法, >
  • ActsAsCsv 预计会被许多类继承的类包含(例如某种BaseModel),

时会产生进一步的优势

  • 当使用acts_as_csv 方法 > 比仅包含 InstanceMethods
  • acts_as_csv 需要一个参数,例如 acts_as_csv :separator =>; “”

The original code allows you to do this:

class A
  include ActsAsCsv
end

class B < A
  acts_as_csv
end

While using inheritance is more a matter of taste in this case it would be cleaner if

  • more methods than just acts_as_csv would be added similarly to A
  • ActsAsCsv would be expected to be included by a class from which many classes inherit (like some kind of BaseModel)

Further advantage arise when

  • the method acts_as_csv is more elaborate than just including InstanceMethods
  • acts_as_csv takes an argument, for example acts_as_csv :separator => " "
新一帅帅 2024-12-27 18:31:45

优点之一是代码(和原始作者)与后来推理代码的人之间的目的沟通。 (以及允许参数的机制。)

acts_as_csv 说明了 RubyCsv 行为的一个方面。

include ActsAsCsv 的声明性较少。它是否提供了额外的方法,是否从根本上改变了底层类的功能,或者两者兼而有之,或者......?在阅读文档之前你不会知道。在阅读 acts_as_csv 的文档之前,您可能也不知道,但它更具沟通性。

这是“这就是我”和“这就是我可能做的”之间的区别。不要陷入具体的例子中——考虑正在做什么以及如何做的机制。

这种机制是 Ruby 代码看起来像它试图解决的问题而不仅仅是 Ruby 的原因之一。这是实现 micro-DSL 的一种方法,有助于使 Ruby 尽可能具有表现力。

One advantage is communication of purpose, between the code (and original writer) and those reasoning about the code later. (And the mechanics of allowing parameters.)

acts_as_csv states an aspect of RubyCsv's behavior.

include ActsAsCsv is less declarative. Does it provide additional methods, does it fundamentally alter the functionality of the underlying class, or both, or...? You won't know until you read the docs. You might not know until you read the docs for acts_as_csv, either, but it's more communicative.

It's the difference between "this is what I am", and "this is what I may do". Don't get caught up in the specific example–consider the mechanics of what is being done, and how.

This mechanism is one reason Ruby code can look like the problem it's trying to solve instead of just Ruby. It's one way of implementing the micro-DSLs that help make Ruby as expressive as it is.

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