Пространства имен и Mixins - PullRequest
       12

Пространства имен и Mixins

0 голосов
/ 27 сентября 2011

Я пытаюсь очистить наши пространства имен. По сути, наша установка похожа на

class myClass
 include myModule1
 include myModule2

 @important_var   #critical instance variable

По сути, @important_var - это обработчик telnet, к которому должны обращаться почти все методы. Это прекрасно работает с настройкой прямо сейчас. К сожалению, myModule1 и myModule2 становятся огромными. Поэтому я продолжаю сталкиваться с коллизиями пространства имен для методов.

Я бы хотел получить доступ к методам с помощью модуля-оболочки, например:

myClass_instance.myModule1.a_method

Но я не могу понять, как сделать это или какую-нибудь другую более чистую идею об именах?

1 Ответ

2 голосов
/ 28 сентября 2011

Основываясь на идее построения соглашения об именах для методов внутри модулей, я подготовил автоматизированную версию:

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).Кроме того, вы получаете метод, называемый префиксом.Этот метод перенаправляет вызов в оригинальный модуль-метод.Смотрите пример в конце кода.

...