关于ruby:在类和方法中定义类实例变量之间的区别是什么。

What's the difference between defining class instance variable in a class and a method. Why?

好吧,就像上面显示的标题,下面两个类实例变量之间的区别是什么?

1
2
3
4
class Document
  @default_font = :Arial
  ...
end

1
2
3
4
5
6
class Document
  def foo
    @default_font = :Arial
  end
  ...
end

有人能向我解释吗?非常感谢你。


第二个场景不是类实例变量。它是一个普通的旧实例变量。


我没有看到原始邮件的最终答案。我最近读了罗斯奥尔森的《雄辩的鲁比》,所以决定把我的收获加在这里。

第一个示例定义单个-@变量的作用域是类作用域,即,如果关键字self出现在方法定义之外但仍在类定义内,则它将引用对象文档,而对象文档又是类的实例。

因此,第一个示例定义了一个类实例变量,即变量@default_font是对象文档的一个实例变量,一个类对象。

该类实例变量只能通过类级访问器方法访问,例如document.default_字体,而不是说,document.default_字体的_实例

因此,如果定义attr_访问器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
2
3
4
5
6
7
8
9
10
11
12
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_字体是一个实例变量,只能由类文档的实例化对象引用。

1
2
3
4
5
6
7
8
9
10
11
12
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
2
3
4
5
6
7
8
9
10
11
12
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


在第一种情况下,变量既不是类变量(应该以@@开头),也不是实例变量。它只是一个局部变量,在当前范围之外不可用,甚至在实例方法内也不可用。

第二个是实例变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Document
  attr_accessor :var1, :var2
  @var1 = 1
  puts @var1 + 2

  def initialize
    @var2 = 4
    puts @var2**2
    #puts @var1 + 6
  end

end

1.9.2p0 :208 > class Document
1.9.2p0 :209?>     attr_accessor :var1, :var2
1.9.2p0 :210?>     @var1 = 1
1.9.2p0 :211?>     puts @var1 + 2
1.9.2p0 :212?>  
1.9.2p0 :213 >       def initialize
1.9.2p0 :214?>         @var2 = 4
1.9.2p0 :215?>         puts @var2**2
1.9.2p0 :216?>         #puts @var1 + 6
1.9.2p0 :217 >         end
1.9.2p0 :218?>  
1.9.2p0 :219 >     end
3
 => nil
1.9.2p0 :220 > d = Document.new
16
 => #<Document:0x1a2f0c @var2=4>

实例方法中的@var1 + 6给出了一个错误。