Created
November 6, 2012 06:43
-
-
Save keithrbennett/4023075 to your computer and use it in GitHub Desktop.
Class Variables vs. Class Instance Variables
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
=begin | |
The "Class Variable" Method in class GuidProvider1 (the "@@" notation) is | |
simpler to use, but violates the principle that the object that owns a | |
variable is the only one who can directly read or modify it. That is, there | |
is no privacy or protection, in that there is no way the instances can be | |
prevented from reading and writing to the variable (for example, the 'next' | |
instance method does both). | |
In contrast, the "Class Instance Variable" single @ notation as shown in | |
GuidProvider2 behaves in a way that is consistent with instance variables in | |
other contexts (that is, within instance methods). The variables are not | |
readable directly, but instead must be explicitly exposed by providing a | |
class getter method. In the example, a getter but not a setter is | |
defined so that instances cannot directly modify the variable. | |
=end | |
# "Class Variable" Method | |
class GuidProvider1 | |
@@highest_seqno = 0 | |
def next | |
@@highest_seqno += 1 | |
end | |
def self.highest_seqno | |
@@highest_seqno | |
end | |
end | |
guid_provider = GuidProvider1.new | |
50.times { guid_provider.next } | |
puts "Highest sequence number for GuidProvider1 is #{guid_provider.class.highest_seqno}" | |
# "Class Instance Variable" Method | |
class GuidProvider2 | |
@highest_seqno = 0 | |
class << self | |
attr_reader :highest_seqno | |
end | |
def self.next | |
@highest_seqno += 1 | |
end | |
def next | |
self.class.next | |
end | |
end | |
guid_provider = GuidProvider2.new | |
5.times { guid_provider.next } | |
puts "Highest sequence number is #{GuidProvider2.highest_seqno}" | |
puts "Can't write to it, this will throw an error because we defined a getter but not a setter:" | |
guid_provider.highest_seqno = 3 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Kieth, another thing to be aware of is that @@ variables are not protected; that is, there is only one variable for the entire class heirarchy, and subclasses can freely modify it:
This is bad because it ignores any invariants that might be required for the parent class to behave correctly, and errors of this sort can be very hard to track down. @@class_variables have been on the "deprecated, avoid this" list for a long, long time.