我的团队一直在阅读现有的ruby代码以建立我们的理解。即使有研究,我们也经常发现我们不太了解的事情。请评论以下问题。
对于以下代码,为什么在模块名称下定义了class << self
?这是否意味着使用模块名称定义类?
module GravatarImageTag
class << self
attr_accessor :configuration
end
为什么作者定义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
为什么作者在方法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
感谢。
答案 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