Reputation: 175
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.
Upvotes: 0
Views: 267
Reputation: 83
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
Upvotes: 0
Reputation: 3919
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.
Upvotes: 0
Reputation: 81691
The second scenario isn't a class instance variable. It's a plain old instance variable.
Upvotes: 1