我没有看到原始帖子的最终答案。我最近读了 Russ Olsen 的《Eloquent Ruby》一书,所以决定在这里补充一下。
第一个例子定义单@变量的作用域是一个类作用域,也就是说,如果关键字 self 出现在方法 def 之外但仍在类定义中,它将引用对象 Document,而后者又是 Class 类的一个实例。
因此第一个例子定义了一个类实例变量,即变量@default_font是一个类对象Document的实例变量。
只能通过类级别的访问器方法访问该类实例变量,例如 Document.default_font,而不是 an_instance_of_Document.default_font
所以如果你定义 attr_accessors:
class Document
@default_font = :Arial # this is a class instance variable,
# def self.default_font
# @default_font
# end
#
# def self.default_font=(font)
# @default_font = font
# end
# or replace the above two class methods with the following
class << self
attr_accessor :default_font
end
end
这是一些 irb 输出:
1.9.3p429 :002 > require './document.rb'
=> true
1.9.3p429 :004 > Document.default_font
=> :Arial
1.9.3p429 :005 > Document.default_font = :Times
=> :Times
1.9.3p429 :006 > Document.default_font
=> :Times
1.9.3p429 :007 > doc = Document.new
=> #<Document:0x007fe6730d8228>
1.9.3p429 :008 > doc.default_font
NoMethodError: undefined method `default_font' for #<Document:0x007fe6730d8228>
原帖中的第二个例子在def方法之外没有包含单@变量定义,说明这里的@default_font是一个实例变量,只能被类Document的实例化对象引用.
class Document
def default_font=(font)
@default_font = font # this defines and set an instance variable
end
def default_font
@default_font # this defines an instance variable
end
# or above two defs can be replaced by the following
attr_accessor :default_font # this defines the instance variable and access methods
end
这是一些 irb 输出:
1.9.3p429 :001 > require './document.rb'
=> true
1.9.3p429 :002 > Document.default_font
NoMethodError: undefined method `default_font' for Document:Class
1.9.3p429 :003 > doc = Document.new
=> #<Document:0x007ffbf1136f88>
1.9.3p429 :004 > doc.default_font
=> nil
1.9.3p429 :005 > doc.default_font = :Arial
=> :Arial
1.9.3p429 :006 > doc.default_font
=> :Arial