#!/usr/bin/env ruby
class Something
@@class_variable = 0
def initialize( name )
@@class_variable += 1
@name = name
end
def value
"#{@name},#{@@class_variable}"
end
end
class SomethingElse < Something
def initialize( name )
super(name)
end
end
joe = Something.new("Joe")
puts "Joe = #{joe.value}"
mary = Something.new("Mary")
puts "Mary = #{mary.value}"
sam = SomethingElse.new("Sam")
puts "Sam = #{sam.value}"
puts "Finished creating. Now Joe = #{joe.value}, Mary = #{mary.value}, and Sam = #{sam.value}"
Class variables are shared among all subclasses.
class SomethingEntirelyDifferent < SomethingElse
@@class_variable = 0
def initialize( name )
super(name)
end
end
puts
ferdinand = SomethingEntirelyDifferent.new("Ferdinand")
puts "Ferdinand = #{ferdinand.value}"
puts "Created subclass with same classvariable. Now Joe = #{joe.value}, Mary = #{mary.value}, and Sam = #{sam.value}"
Class variables are not shadowed. They are scoped wrt the inheritance chain.
Class variables are candidates for unintentional side-effects.
class SomethingAgain < SomethingElse
@class_instance_variable = 0
class << self; attr_accessor :class_instance_variable end
attr_accessor :instance_variable
def initialize( name )
self.class.class_instance_variable += 1
super(name)
end
end
albert = SomethingAgain.new("Albert")
puts "Albert = #{albert.value}"
puts "Albert's class = #{albert.class.name} && class instance = #{albert.class.class_instance_variable}"
jane = SomethingAgain.new("Jane")
puts "Created subclass with class instance variable, and two instances."
puts "Jane's class = #{jane.class.name} && class instance = #{jane.class.class_instance_variable}"
puts "Albert's class = #{albert.class.name} && class instance = #{albert.class.class_instance_variable}"
Class instance variables are attached to an object's class object.
class SomethingMore < SomethingAgain
@class_instance_variable = 1138
def initialize( name)
super(name)
end
end
mike = SomethingMore.new("Mike")
puts "Mike = #{mike.value}"
puts "Mike's class = #{mike.class.name} && class instance = #{mike.class.class_instance_variable}"
puts "Created subclass of class with class instance variable, with its own class instance variable"
Class instance variables aren't visible to subclasses.
Class instance variables are required on subclasses when base-class methods that read or write them.
puts "Albert's class = #{albert.class.name} && class instance = #{albert.class.class_instance_variable}"
Class instance variables are not visible to other subclasses in the inheritance chain.
All in all, the @@class variables encourage collusive coding and appear to carry a high risk of causing race conditions and other unintentional side-effects. The @class instance variables carry a somewhat lesser risk. Barring some obscure trick, a class instance variable is always associated with precisely one class. But even with class instance variables, multiple object instances can gain access to the variable through their own "class" property, with the potential for unintended side-effects.
No comments:
Post a Comment