#!/usr/bin/ruby1.8 -- =begin static-vars.rb Experimental library that adds Java-esque "static variable" functionality to all Ruby classes. These static variables differ from class variables particularly in that they are shadowed in overriding subclasses rather than writing back. Author: Matthew Kerwin Copyright (C) 2009 Matthew Kerwin. All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Matthew Kerwin. 4. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =end $__static_vars = {} unless $__static_vars class Class # # Like ancestors, but grabs only true superclasses. # def superclasses c = self real = [] until c.nil? real << c c = c.superclass end real end # # Get the java-esque name of this Class. # def java_name superclasses.reverse.map{|a|a.name}.join('.') end # # Define a static variable. # def static_variable_set var_name, value = nil jn = java_name.to_sym $__static_vars[jn] = {} unless $__static_vars.has_key?(jn) $__static_vars[jn][var_name.to_s.to_sym] = value end alias :var :static_variable_set # # Returns true if the given static variable is defined. # def static_variable_defined? var_name var_name = var_name.to_s.to_sym superclasses.each do |cl| jn = cl.java_name.to_sym if $__static_vars && $__static_vars[jn] && $__static_vars[jn].has_key?(var_name) return true end end false end # # Retrieve a static variable. # def static_variable_get var_name var_name = var_name.to_s.to_sym superclasses.each do |cl| jn = cl.java_name.to_sym if $__static_vars && $__static_vars[jn] && $__static_vars[jn].has_key?(var_name) return $__static_vars[jn][var_name] end end raise NoMethodError end # # Returns an Array containing all the static variables accessible by this class. # def static_variables vars = {} superclasses.each do |cl| jn = cl.java_name.to_sym if $__static_vars && $__static_vars[jn] $__static_vars[jn].keys.each{|k| vars[k.to_s] = true } end end vars.keys end def method_missing method, *args superclasses.each do |cl| jn = cl.java_name.to_sym if args.length == 0 && $__static_vars && $__static_vars[jn] && $__static_vars[jn].has_key?(method) return $__static_vars[jn][method] end end super method, *args end # def respond_to? method # static_variable_defined?(method) unless super(method) # end # def method_defined? method # static_variable_defined?(method) unless super(method) # end end if __FILE__ == $0 def try &block begin yield rescue => er puts [er] + er.backtrace.map{|e|"\t#{e}"} end end # ------------------------------------------------------------------- puts "\n1. create a class:" class MyClass end print "MyClass.some_var => " try { puts MyClass.some_var.inspect } # ------------------------------------------------------------------- puts "\n2. create a class with 'some_var' defaulted to nil:" class MyClass self.var 'some_var' end print "MyClass.some_var => " try { puts MyClass.some_var.inspect } # ------------------------------------------------------------------- puts "\n3. create a class with 'some_var' equal to 7:" class MyClass self.var 'some_var', 7 end print "MyClass.some_var => " try { puts MyClass.some_var.inspect } # ------------------------------------------------------------------- puts "\n4 change it to 8:" MyClass.var 'some_var', 8 print "MyClass.some_var => " try { puts MyClass.some_var.inspect } # ------------------------------------------------------------------- puts "\n5. create a subclass with 'some_var' with a value of 'foo':" class MySubClass < MyClass self.var 'some_var', 'foo' end print "MySubClass.some_var => " try { puts MySubClass.some_var.inspect } print "MyClass.some_var => " try { puts MyClass.some_var.inspect } # ------------------------------------------------------------------- puts "\n6. testing other static_var methods:" print "MyClass.static_variables => " puts MyClass.static_variables.inspect print "MyClass.static_variable_defined?('foo') => " puts MyClass.static_variable_defined?('foo') print "MyClass.static_variable_defined?('some_var') => " puts MyClass.static_variable_defined?('some_var') print "MyClass.static_variable_set('some_var', 'poot') =>\n" MyClass.static_variable_set 'some_var', 'poot' print " MyClass.some_var => " puts MyClass.some_var.inspect print " MySubClass.some_var => " puts MySubClass.some_var.inspect end