Руби, как сбросить методы класса - PullRequest
1 голос
/ 11 января 2010

Используя module_eval, мой код позволяет мне динамически создавать и добавлять новые методы в класс на основе входных параметров. Смотрите этот пост для примера Ruby class_eval и доходность

Теперь мой вопрос: как мне вернуть класс к его исходным методам? Есть ли простой метод, который я могу использовать, чтобы вернуть класс в исходное состояние? Причина этого в том, что после добавления новых методов в класс они сохраняются, и мне нужно от них избавиться, если я создаю новый объект с другим набором методов.

Также я должен извиниться, если этот вопрос не совсем имеет смысла, я проснулся в течение 24 часов и, вероятно, мне нужно было немного отдохнуть, чтобы мыслить ясно. Если это не ясно, я могу привести пример. Заранее благодарны за Вашу помощь.

Ответы [ 3 ]

2 голосов
/ 11 января 2010

Редактировать: Добавлено полное решение

Если вы храните список методов, добавленных в предыдущем посте, вы можете использовать remove_method, чтобы удалить эти методы, например:

class MyTest
  @@methods_list = []

  def self.show_methods
    @@methods_list
  end

  def self.reset_methods
    @@methods_list.each do |method|
      remove_method(method)
    end
    @@methods_list = []
  end

  def self.add_methods
    define_method("method1")  { puts "This is method1" }
    define_method("method2")  { puts "This is method2" }
    true
  end

  def self.method_added(method_name)
    @@methods_list << method_name.to_s
    puts "Added: " + method_name.to_s + ", list: " + @@methods_list.inspect
  end
end

Теперь вы можете попробовать следующее:

>> require 'mytest.rb'
>> t = MyTest.new # => #<MyTest:0x2b1e293247f0>
>> MyTest.add_methods
Added: method1, list: ["method1"]
Added: method2, list: ["method1", "method2"]
>> t.method1 # Method is available:
This is method1
>> MyTest.reset_methods
>> t.method1 # Method is undefined now, so we'd expect an error
NoMethodError: undefined method `method1' for #<MyTest:0x2b1e293247f0>
    from (irb):6
1 голос
/ 11 января 2010

Я бы взял один из двух способов:

  • либо переместите исходные методы класса в модуль, который вы можете повторно include позже
  • или используйте module_eval для подкласса исходного класса и просто получите новый подкласс, когда вы хотите выполнить сброс.

Второе немного легче сделать:

 subklass = Class.new(MyAwesomeClass)
 subklass.module_eval #...

 # ok, I'm done, I want to reset
 subklass = Class.new(MyAwesomeClass)
0 голосов
/ 11 января 2010

Я не знаю такой возможности, и я, вероятно, подумал бы, что ваш код мог бы быть лучше структурирован, если он вам нужен, но есть несколько вещей, которые вы можете попробовать:

  • Переопределите новые методы вариантами, которые будут генерировать исключение или ничего не делать. Если вы знаете имена новых методов, это было бы довольно легко сделать.
  • Вместо добавления методов в один класс создайте анонимный подкласс, который наследуется от базового класса, к которому вы добавляете свои методы. (См. Ответ на на этот вопрос , чтобы узнать, как это сделать.) Затем ваш базовый класс все еще не модифицирован, поэтому его не нужно будет сбрасывать.

НТН

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...