使用Class vs Module在Ruby中打包代码 [英] Using Class vs Module for packaging code in Ruby

查看:93
本文介绍了使用Class vs Module在Ruby中打包代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

比方说,我有一堆没有持久状态的相关函数,例如字符串差异包中的各种操作.我可以在类或模块中定义它们(使用self),并且可以使用完全相同的方式对其进行访问:

Let's say I have a bunch of related functions that have no persistent state, say various operations in a string differencing package. I can either define them in a class or module (using self) and they can be accessed the exact same way:

class Diff
  def self.diff ...
  def self.patch ...
end

module Diff
  def self.diff ...
  def self.patch ...
end

然后我可以做Diff.patch(...).哪个是更好"(或正确")?

I can then do Diff.patch(...). Which is 'better' (or 'correct')?

我需要将它们归类的主要原因是名称空间问题,常见的函数名称都在其他地方使用.

The main reason I need to group them up is namespace issues, common function names are all used elsewhere.

将示例从矩阵更改为差异. Matrix是一个可怕的示例,因为它确实有状态,并且每个人都开始解释为什么将它们编写为方法而不是回答实际问题更好. :(

Changed example from matrix to diff. Matrix is a terrible example as it does have state and everyone started explaining why it's better to write them as methods rather than answer the actual question. :(

推荐答案

在您的两个示例中,您实际上并没有在ClassModule中定义方法.您正在一个对象上定义单例方法,该对象恰巧是ClassModule,但几乎可以是任何对象.这是String的示例:

In your two examples, you are not actually defining methods in a Class or a Module; you are defining singleton methods on an object which happens to be a Class or a Module, but could be just about any object. Here's an example with a String:

Diff = "Use me to access really cool methods"

def Diff.patch
  # ...
end

您可以执行这些操作中的任何一个,并且都可以使用,但是将相关方法分组的最佳方法是在Module中作为普通实例方法(即,不使用self.):

You can do any of these and that will work, but the best way to group related methods is in a Module as normal instance methods (i.e. without self.):

module Diff
  extend self  # This makes the instance methods available to the Diff module itself
  def diff ... # no self.
  def patch ...
end

现在您可以:

  • 从任何类(带有include Diff)或任何对象(带有extend Diff)中使用此功能
  • 这种用法的一个例子是extend self行,它可以调用Diff.patch.
  • 即使在全局名称空间中也使用这些方法
  • use this functionality from within any Class (with include Diff) or from any object (with extend Diff)
  • an example of this use is the extend self line which makes it possible to call Diff.patch.
  • even use these methods in the global namespace

例如,在irb中:

class Foo
  include Diff
end
Foo.new.patch # => calls the patch method
Diff.patch    # => also calls Diff.patch
include Diff  # => now you can call methods directly:
patch         # => also calls the patch method

注意:extend self将修改" Diff模块对象本身,但对模块的包含内容没有任何影响. def self.foo也会发生同样的事情,foo对于包括它的任何类都不可用.简而言之,只有Diff的实例方法与include(或extend)一起导入,而不是单例方法.只有子类可以继承实例和单例方法.

Note: the extend self will "modify" the Diff module object itself but it won't have any effect on inclusions of the module. Same thing happens for a def self.foo, the foo won't be available to any class including it. In short, only instance methods of Diff are imported with an include (or an extend), not the singleton methods. Only subclassing a class will provide inheritance of both instance and singleton methods.

当您实际上希望包含一个模块来提供实例方法和单例方法时,这并不完全容易.您必须使用self.included挂钩:

When you actually want the inclusion of a module to provide both instance methods and singleton methods, it's not completely easy. You have to use the self.included hook:

module Foo
  def some_instance_method; end

  module ClassMethods
    def some_singleton_method; end
  end

  def self.included(base)
    base.send :extend, ClassMethods
  end

  def self.will_not_be_included_in_any_way; end
end

class Bar
  include Foo
end
# Bar has now instance methods:
Bar.new.some_instance_method  # => nil
# and singleton methods:
Bar.some_singleton_method   # => nil

这篇关于使用Class vs Module在Ruby中打包代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆