From: Trans Date: 2006-12-05T12:08:21+09:00 Subject: Method Namespace I have need for a general purpose simple namespace construction. Not selector namespaces, mind you, just a method namespace. I made the following attempt. So close! But it fails b/c if a method is already defined in the class and the namespace module being added also has a method of the same name they will clash. I worked around it by aliasing the method with a temporary name then realiasing it to the original name. This words EXCEPT when super is called in the method (see the test case a the bottom). Anone have any better ways of implementing? Thanks, T. # namespace.rb require 'facet/functor' require 'facet/module/basename' class Module # Define a simple namespace. # # class A # attr_writer :x # namespace :inside do # def x; @x; end # end # end # # a = A.new # a.x = 10 # a.inside.x #=> 10 # a.x # no method error def namespace( mod, &blk ) # If block is given then create a module, othewise # get the name of the module. if block_given? name = mod.to_s mod = Module.new(&blk) else name = mod.basename.downcase mod = mod.dup end # We have to work around name clashes. nameclashes = mod.instance_methods & instance_methods nameclashes.each do |n| alias_method "#{n}:namespace", n end # Include the module. This is neccessary, otherwise # Ruby won't let us bind the instance methods. include mod # Undefine the instance methods of the module. mod.instance_methods.each{ |m| undef_method m } # Redefine the methods that clashed. nameclashes.each do |n| alias_method n, "#{n}:namespace" undef_method "#{n}:namespace" end # Add a method for the namespace that delegates # via the Functor to the module instance methods. define_method(name) do Functor.new(mod) do |op, base, *args| base.instance_method(op).bind(self).call(*args) end end end end # begin test require 'test/unit' class TestNamespace1 < Test::Unit::TestCase module M def x; "x"; end end class C namespace M end def test_01 c = C.new assert_equal('x', c.m.x) end def test_02 c = C.new assert_raises(NoMethodError){ c.x } end end class TestNamespace2 < Test::Unit::TestCase class B def x; 1; end end class C < B def x; super; end namespace :m do def x; "x"; end end end def test_01 c = C.new assert_equal('x', c.m.x) end # THIS FAILS !!! def test_02 c = C.new assert_equal(1, c.x) end end