请求深入了解ruby代码

时间:2014-06-13 13:28:06

标签: ruby

我的团队一直在阅读现有的ruby代码以建立我们的理解。即使有研究,我们也经常发现我们不太了解的事情。请评论以下问题。

问题1

对于以下代码,为什么在模块名称下定义了class << self?这是否意味着使用模块名称定义类?

module GravatarImageTag

  class << self
    attr_accessor :configuration
  end

问题2

为什么作者定义class << self并继续使用self.定义方法?我们的理解是,您可以在以self.开头的块中定义class << self方法,而不是为每种方法重复self.

module GravatarImageTag

  class << self
    attr_accessor :configuration
  end

  def self.configuration
    @configuration ||= Configuration.new
  end

  def self.configure
    yield(configuration)
  end

问题3

为什么作者在方法self.include(base)中使用类名而不是self?此外,对于这个文件的结构,什么类是self.include(base)的成员?这与问题1有关。

module GravatarImageTag

  class << self
    attr_accessor :configuration
  end

  def self.configuration
    @configuration ||= Configuration.new
  end

  def self.configure
    yield(configuration)
  end

  class Configuration
     attr_accessor :default_image, :filetype, :include_size_attributes,
       :rating, :size, :secure

     def initialize
        @include_size_attributes = true
     end
  end

  def self.included(base)
    GravatarImageTag.configure { |c| nil }
    base.extend ClassMethods
    base.send :include, InstanceMethods
  end   

感谢。

1 个答案:

答案 0 :(得分:0)

小位说明:

class << self不仅仅是一种声明类方法的方法(尽管可以这样使用)。可能你已经看到了一些用法:

class Foo
  class << self
    def a
      print "I could also have been defined as def Foo.a."
    end
  end
end

这有效,相当于def Foo.a,但它的工作方式有点微妙。秘诀是self在该上下文中引用了对象Foo,其类是Class的唯一匿名子类。该子类称为Foo的本征类。因此,def a创建了一个名为in Foo的本征类的新方法,可通过常规方法调用语法访问:Foo.a

现在让我们看一个不同的例子:

str = "abc"
other_str = "def"

class << str
  def frob
    return self + "d"
  end
end

print str.frob # => "abcd"
print other_str.frob # => raises an exception, 'frob' is not defined on other_str

此示例与最后一个示例相同,但最初可能很难说。 frob的定义不是String类,而是str的本征类,String的唯一匿名子类。因此,str具有frob方法,但String的实例通常不会。我们也可以覆盖String的方法(在某些棘手的测试场景中非常有用)。

通过David Seiler