문제

Well, like the title shown, what's the difference between the two class instance variables below

class Document
  @default_font = :Arial
  ...
end

And

class Document
  def foo
    @default_font = :Arial
  end
  ...
end

Is there anyone can explain it to me. Thank you very much.

도움이 되었습니까?

해결책

In your first case, the variable is neither a class variable(which should have started with @@, nor an instance variable. It is simply a local variable not available outside the current scope, not even within the instance methods.

The second is an instance variable.

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> 

The @var1 + 6 inside the instance method gives an error.

다른 팁

The second scenario isn't a class instance variable. It's a plain old instance variable.

I didn't see a final answer to the original post. I recently read the book "Eloquent Ruby" by Russ Olsen, so decided to add my take-away here.

The scope in which the first example defines the single-@ variable is a class-scope, i.e., if the keyword self were to appear outside a method def but still within the class definition, it would reference the object Document, which is in turn an instance of the Class class.

The first example therefore defines a class instance variable, i.e., the variable @default_font is an instance variable of the object Document, a class object.

This class instance variable should only be accessed via the class level accessor methods, e.g., Document.default_font, rather than say, an_instance_of_Document.default_font

So if you define the 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

Here's some irb output:

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>

The fact that the second example in the original post does not contain a single-@ variable definition outside a method def, indicates that the @default_font here is an instance variable, which can only be referenced by an instantiated object of class 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

Here's some irb output:

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 
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top