Скопируйте все методы из одного класса в другой на лету - PullRequest
2 голосов
/ 19 марта 2012

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

def partial(cls)
  cls.instance_methods(false).each do |method_name|
    define_method(method_name) do
      cls.new.method(method_name.to_sym).call
    end
  end
end

Методы создаются на лету с использованием define_method в первом классе, поэтому я не могу просто использовать include. В приведенном выше коде передается cls, затем он находит все методы экземпляра, которые фактически написаны в этом классе, а не те, которые он наследует, и затем создает новый метод с тем же именем. Когда этот метод вызывается, он фактически вызывает другой класс со своим методом с тем же именем. Это прекрасно работает, если у меня нет аргументов. Я проверил условие, чтобы увидеть, есть ли у него аргументы, а затем вызвал метод с аргументами, но он не очень хорошо обрабатывал хэши. Он сделал хеш в качестве массива для аргумента, а это не то, что я хотел.

Мне было интересно, существует ли простой способ буквально сказать: «Эй, вы знаете этот метод, каким бы он ни был, буквально сделать то же самое для этого другого класса».

Ответы [ 3 ]

2 голосов
/ 19 марта 2012

Вы также можете попробовать DelegateClass :

class NamedArray < DelegateClass(Array)
  def initialize n
    @name = n
    super(Array.new)
  end
  def sayName
    "My name is #{@name}"
  end
end
0 голосов
/ 19 марта 2012
0 голосов
/ 19 марта 2012

Если все методы идентичны, почему бы просто не определить их в общем модуле, который вы включаете в оба класса?Вы упоминаете, что не используете include, потому что методы определены динамически, но это не значит, что они не будут найдены при смешивании в модуле:

module Foo
  def self.make_an_example_method(name)
    define_method(name) do |*args|
      puts "I am #{name} called with (#{args.inspect})"
    end
  end
end

class A
  include Foo
end

class B
  include Foo
end

Foo.make_an_example_method(:example)
Foo.make_an_example_method(:dynamic)

A.new.example         # => I am example called with ([])
B.new.dynamic(1,2,3)  # => I am dynamic called with ([1, 2, 3])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...