Как динамически определить метод класса, который будет ссылаться на локальную переменную снаружи? - PullRequest
21 голосов
/ 15 августа 2010
class C
end

var = "I am a local var outside"

C.class_eval do
   def self.a_class_method
     puts var 
   end
end

Я знаю, это не правильно, потому что def создал новую область видимости.Я также знаю, что использование define_method может создать метод экземпляра без создания новой области, но моя точка зрения заключается в том, как определить метод класса .

Ответы [ 3 ]

51 голосов
/ 15 августа 2010

Методы класса на самом деле не существуют в Ruby, они просто одноэлементные методы объекта класса. Синглтон-методы на самом деле тоже не существуют, они просто обычные методы экземпляра синглтон-класса объекта.

Поскольку вы уже знаете, как определять методы экземпляра (используя Module#define_method), вы уже знаете все, что вам нужно знать. Вам просто нужно вызвать class_eval на синглтон-классе C вместо C:

(class << C; self end).class_eval do
  define_method(:a_class_method) do
    puts var 
  end
end

Текущие версии Ruby имеют метод singleton_class, чтобы сделать это проще:

C.singleton_class.class_eval do
  define_method(:a_class_method) do
    puts var 
  end
end

Но на самом деле текущие версии Ruby также имеют Module#define_singleton_method, поэтому в данном конкретном случае это не нужно:

C.define_singleton_method(:a_class_method) do
  puts var 
end
1 голос
/ 13 декабря 2016

Вы можете сделать это просто так

class << C
  define_method(:a_class_method) do
     # do something
  end
end
0 голосов
/ 06 мая 2019
C.instance_eval do
  def class_method
    "This is class method"
  end
end

instance_eval : определяет одноэлементные методы для объекта (что приводит к методам класса, когда он вызывается для объекта класса).

class_eval : определяет обычные методы экземпляра

...