From: Dan Doel Date: 2003-08-22T09:51:47+09:00 Subject: Re: Class variables - a surprising result Hal E. Fulton wrote: >Well, I think that in Java/C++ they're inherited but not shared. >In Ruby they're shared. > >Of course, there's an ugly trick that gets around this... can anyone >guess it? David showed it to me once. > Are you referring to the "class << self.class" trick (alluded to by Matz and others elsewhere in the thread)? If you think it's ugly, you can always wrap methods around it to make it look more like normal access, or at least more normal by Java standards. :) Code below. - Dan class Module # Java style class variables # if class Foo defines a static variable, all subclasses can see it # but it can be overrided by re-declaring, so to speak. # # static_var :foo (re-)declares a static class variable # static variable are modifiable in subclasses unless redeclared, as they # are in Java def static_var(*args) static_var_writer *args static_var_reader *args end def static_var_reader(*args) args.each do |symbol| eval <<-EOF def #{name}.#{symbol.id2name} class << #{name} @#{symbol.id2name} end end EOF end end def static_var_writer(*args) args.each do |symbol| eval <<-EOF def #{name}.#{symbol.id2name}=(value) class << #{name} proc do |e| @#{symbol.id2name} = e end end.call value end EOF end end # More restrictive class instance variables # These variables are shared by all instances of the class, but # subclasses cannot see or modify them through the accessors. The # accessors will still exist, but they will deal with the subclass' # own class instance variable, and not interfere with that of the # superclass def cinst_var(*args) cinst_var_writer *args cinst_var_reader *args end def cinst_var_reader(*args) args.each do |symbol| class_eval <<-EOF def self.#{symbol.id2name} class << self @#{symbol.id2name} end end EOF end end def cinst_var_writer(*args) args.each do |symbol| class_eval <<-EOF def self.#{symbol.id2name}=(value) class << self proc do |e| @#{symbol.id2name} = e end end.call value end EOF end end end class Foo static_var :var cinst_var :var2 end class Bar < Foo end class Baz < Foo static_var :var end Foo.var = 5 p Foo.var p Bar.var p Baz.var Bar.var = 6 p Foo.var p Bar.var p Baz.var Baz.var = 7 p Foo.var p Bar.var p Baz.var Foo.var2 = 8 p Foo.var2 p Bar.var2 p Baz.var2 Bar.var2 = 9 p Foo.var2 p Bar.var2 p Baz.var2 Baz.var2 = 10 p Foo.var2 p Bar.var2 p Baz.var2