Ответ 1
Я думаю, что в Ruby 1.9 вы можете сделать это:
class A
define_singleton_method :loudly do |message|
puts message.upcase
end
end
A.loudly "my message"
# >> MY MESSAGE
Это полезно, если вы пытаетесь создать метапрограммирование методов класса:
def self.create_methods(method_name)
# To create instance methods:
define_method method_name do
...
end
# To create class methods that refer to the args on create_methods:
???
end
Мой ответ, чтобы следовать...
Я думаю, что в Ruby 1.9 вы можете сделать это:
class A
define_singleton_method :loudly do |message|
puts message.upcase
end
end
A.loudly "my message"
# >> MY MESSAGE
Я предпочитаю использовать send to call define_method, и мне также нравится создавать метаклассовый метод для доступа к метаклассу:
class Object
def metaclass
class << self
self
end
end
end
class MyClass
# Defines MyClass.my_method
self.metaclass.send(:define_method, :my_method) do
...
end
end
Выведено из: Jay и Why, которые также предоставляют способы сделать это красивее.
self.create_class_method(method_name)
(class << self; self; end).instance_eval do
define_method method_name do
...
end
end
end
Обновить: из вклада VR ниже; более сжатый метод (пока вы определяете только один метод таким образом), который по-прежнему остается автономным:
self.create_class_method(method_name)
(class << self; self; end).send(:define_method, method_name) do
...
end
end
но обратите внимание, что использование send() для доступа к приватным методам, таким как define_method(), не обязательно является хорошей идеей (я понимаю, что он уходит в Ruby 1.9).
Это самый простой способ в Ruby 1.8 +:
class A
class << self
def method_name
...
end
end
end
Используется в Rails, если вы хотите динамически определять методы класса:
module Concerns::Testable
extend ActiveSupport::Concern
included do
singleton_class.instance_eval do
define_method(:test) do
puts 'test'
end
end
end
end
Вы также можете сделать что-то подобное, не полагаясь на define_method:
A.class_eval do
def self.class_method_name(param)
puts param
end
end
A.class_method_name("hello") # outputs "hello" and returns nil
Это работает для меня в Ruby 1.9.3
class B
def self.class_method(param)
puts param
end
end
B.class_method("something") # outputs "something".