Question

Je suis deeping en ruby métaprogrammation et ont question suivante.Exemple:

module ExampleAliaser
  def do_example_alias(prefix=:origin)

    class_eval  <<-EOS
       class << self 
           alias_method :#{prefix}_example, :example
           def example
              puts "in aliase will call :#{prefix}_example"
              #{prefix}_example
           end  
        end
    EOS

  end   
end  

class Example1
 def self.example
    puts "Example"
 end 
end


Example1.extend(ExampleAliaser)

class Example1 
 do_example_alias(:origin)
end
class Example2 <  Example1
 do_example_alias(:origin)
end



     Example1.example
    in aliase will call :origin_example
    Example
     => nil 

     Example2.example
in aliase will call :origin_example
in aliase will call :origin_example
in aliase will call :origin_example
    SystemStackError: stack level too deep
        from /Users/igorfedoronchuk/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/irb/workspace.rb:80
    Maybe IRB bug!!

Alors, quand mixin utilisé 2 fois, il provoque une erreur.Quelle est la meilleure façon de corriger de telles choses?Comment faire pour déterminer que le mélange existe et de le retirer avant que la nouvelle de mélange

Était-ce utile?

La solution

Suivre la définition de méthodes pour voir pourquoi ce qui se passe.

Vous devez d'abord définir Example1::example dans la définition de la classe de Example1.Il écrit une chaîne de caractères dans la console.

Ensuite, vous étendre ExampleAliaser.Lorsque vous appelez Example1::do_example_alias, vous alias la méthode example pour origin_example et de redéfinir la méthode example pour écrire une chaîne de caractère à la console et appel origin_example.

Ensuite, vous définissez la classe Example2 pour hériter de Example1, qui a désormais deux méthodes définies sur elle: origin_example et example.Lorsque vous appelez Example2::do_example_alias, vous alias la méthode example pour origin_example.Mais rappelez-vous que example a déjà été redéfini à l'appel origin_example.Donc, effectivement, Example2::example va s'appeler lui-même jusqu'à ce que vous manquez de place sur la pile.


Si vous voulez éviter les double-aliasing, vous pourriez inclure une sorte de garde do_example_alias:

def do_example_alias(prefix = :origin)
  unless methods.include?("#{prefix}_example")
    # do the aliasing
  end
end

Vous pouvez également undef :method_name dans les sous-classes de méthodes de suppression que vous ne voulez plus défini.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top