【问题标题】:Namespaces and Mixins命名空间和混合
【发布时间】:2011-11-26 07:54:37
【问题描述】:

我正在尝试清理我们的命名空间。基本上我们的设置有点像

class myClass
 include myModule1
 include myModule2

 @important_var   #critical instance variable

基本上,@important_var 是一个 telnet 处理程序,几乎所有方法都需要使用它。这适用于现在的设置方式。不幸的是 myModule1 & myModule2 变得越来越大。所以我不断遇到方法的命名空间冲突。

我很想使用模块包装器访问方法,例如:

myClass_instance.myModule1.a_method

但我不知道如何做到这一点或其他一些更简洁的名称间距想法?

【问题讨论】:

  • 类和模块必须以大写字母开头。在你的情况下:myClass -> MyClass, myModule1 -> MyModule1...
  • 你可以用m1_开始MyModule1的每个方法
  • 没有看到代码很难说,但从你的描述来看,听起来需要进行一些重构。 - 您能否将您的方法拆分为直接需要@important_var 的较低级别的管道,并将其他方法与它隔离开来? - 班级真的只有一个责任吗?或者你可以分开吗?等
  • @knut 谢谢..是的,我把名字中的大写字母弄乱了
  • 有点晚了,但这听起来是学习对象聚合和组合的理想时机。它有助于保持事物井井有条而不会弄乱你的命名空间,如果你的组件是从接口继承的,你的代码就会变得不那么紧密......

标签: ruby module namespaces mixins


【解决方案1】:

基于为模块内的方法建立命名约定的想法,我准备了一个自动化版本:

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 包含模块并检查每个方法是否以定义的前缀开头。如果没有定义方法(通过alias)。此外,您还会获得一个名为前缀的方法。此方法将调用转发到原始模块方法。见代码末尾的示例。

【讨论】:

    猜你喜欢
    • 2015-03-29
    • 2012-05-02
    • 2012-03-29
    • 2012-04-03
    • 1970-01-01
    • 2012-09-06
    • 1970-01-01
    • 1970-01-01
    • 2014-04-14
    相关资源
    最近更新 更多