开发者

Namespaces and Mixins

开发者 https://www.devze.com 2023-04-07 20:52 出处:网络
I\'m trying to clean up our namespaces. Basically our setup is somewhat like class myClass include myModule1

I'm trying to clean up our namespaces. Basically our setup is somewhat like

class myClass
 include myModule1
 include myModule2

 @important_var   #critical instance variable

Basically @important_var is a telnet handler that almost a开发者_运维百科ll methods need to get at. This works fine with the way it is setup right now. Unfortunately myModule1 & myModule2 are getting huge. So I keep running into namespace collisions for the methods.

I'd love to access methods with a module wrapper eg:

myClass_instance.myModule1.a_method

But I can't figure out how to do this or some other cleaner name spacing idea?


Based on the idea to build a naming convention for the methods inside the modules I prepared a automated version:

module MyModule1
  def m;  "M1#m  <#{@important_var }>";  end
  #method according naming convention
  def m1_action;  "M1#m1 <#{@important_var }>";  end
end

module MyModule2
  def m;  "M2#m  <#{@important_var }>";  end
  #method according naming convention
  def m2_action;  "M2#m2 <#{@important_var }>";  end
end

class MyClass
  #add prefix to each method of the included module.
  def self.myinclude( mod, prefix )
    include mod
    #alias each method with selected prefix
    mod.instance_methods.each{|meth|      
      if meth.to_s[0..prefix.size-1] == prefix
        #ok, method follows naming convention
      else #store method as alias
        rename = "#{prefix}#{meth}".to_sym
        alias_method(rename, meth)
        puts "Wrong name for #{mod}##{meth} -> #{rename}" 
      end
    }
    #define a method '<<prefix>> to call the methods
    define_method(prefix){ |meth, *args, &block | send "#{prefix}#{meth}".to_sym *args, &block }
  end
  myinclude MyModule1, 'm1_'
  myinclude MyModule2, 'm2_'
  def initialize
    @important_var   = 'important variable' #critical instance variable
  end
end

###################
puts "-------Test method calls--------"

m = MyClass.new
p m.m1_action
p m.m2_action

p m.m #last include wins

puts "Use renamed methods"
p m.m1_m
p m.m2_m
puts "Use 'moduled' methods"
p m.m1_(:m)
p m.m2_(:m)

myinclude includes the module and checks, if each method begins with a defined prefix. If not the method is defined (via alias). In addition you get a method called like the prefix. This method forwards the call to the original module-method. See example in the code end.

0

精彩评论

暂无评论...
验证码 换一张
取 消