Подтвердить что ты не робот

Методы Ruby Singleton для класса и объектов

Я изучаю Ruby Singletons, и я нашел несколько способов определить и получить список методов Singleton класса и объекта.

Методы Singleton класса

Способы определения методов класса singleton:

class MyClass

  def MyClass.first_sing_method
    'first'
  end

  def self.second_sing_method
    'second'
  end

  class << self
    def third_sing_method
      'third'
    end
  end

  class << MyClass
    def fourth_sing_method
      'fourth'
    end
  end
end

def MyClass.fifth_sing_method
  'fifth'
end

MyClass.define_singleton_method(:sixth_sing_method) do
  'sixth'
end

Способы получения списка методов сингл-класса :

#get singleton methods list for class and it ancestors 
MyClass.singleton_methods

#get singleton methods list for current class only  
MyClass.methods(false)

Методы Singleton для объектов

Способы определения методов Singleton

class MyClass
end

obj = MyClass.new

class << obj
  def first_sing_method
    'first'
  end
end

def obj.second_sing_method
  'second'
end

obj.define_singleton_method(:third_sing_method) do
  'third'
end

Способ получения списка методов Singleton

#get singleton methods list for object and it ancestors  
obj.singleton_methods

#get singleton methods list for current object only
obj.methods(false)

Есть ли другие способы сделать это?

4b9b3361

Ответ 1

Прежде всего, способ перечислить методы singleton с помощью singleton_methods. Метод methods возвращает список имен общедоступных и защищенных методов объекта. Кроме того, он определен в классе Object. Попробуйте extend выполнить экземпляр. Это один из самых элегантных способов, поскольку он поддерживает повторное использование кода и кажется мне очень объектно-ориентированным:

class Foo
  def bar
    puts "Hi"
  end
end

module Bar
  def foo
    puts "Bye"
  end
end

f = Foo.new
f.bar
#=> hi

f.extend Bar
f.foo
#=> bye

f.methods(false)
#=> []
# the module we extended from is not a superclass
# therefore, this must be empty, as expected

f.singleton_methods
#=> ["foo"]
# this lists the singleton method correctly

g = Foo.new
g.foo
#=> NoMethodError

Изменить. В комментарии вы спросили, почему methods(false) ничего не возвращает в этом случае. После прочтения кода C кажется, что:

  • methods возвращает все доступные для объекта методы (также входящие в состав модулей)
  • singleton_methods возвращает все однотипные методы для объекта (также входящие в состав модулей) (документация)
  • singleton_methods(false) возвращает все одиночные методы для объекта, но не те, которые объявлены в включенных модулях
  • methods(false) якобы возвращает одиночные методы, вызывая singleton_methods, , но он также передает ему параметр false; будь то ошибка или функция - я не знаю

Надеюсь, это немного разъяснит проблему. Итог: вызов singleton_methods, кажется более надежным.

Ответ 2

Еще несколько способов:

Одноуровневые методы класса

class << MyClass
  define_method :sixth_sing_method do
    puts "sixth"
  end
end

class MyClass
  class << self
    define_method :fourth_sing_method do
      puts "seventh"
    end
  end
end

Одиночные методы объекта

class << obj
  define_method :fourth_sing_method do
    puts "fourth"
  end
end

Далее вы можете использовать define_method и define_singleton_method в комбинации с send, например

obj.send :define_singleton_method, :nth_sing_method, lambda{ puts "nth" }

и всех возможных комбинаций. Чтобы использовать define_method, вам нужно сначала захватить класс singleton, как в этом (то же самое работает и для объектов класса)

singleton_class = class << obj; self end
singleton_class.send :define_method, :nth_sing_method, lambda{ puts "nth" }

Другие способы использования class_eval для объектов одноэлементного класса:

singleton_class.class_eval do
  def nth_sing_method
    puts "nth"
  end
end

И затем вы снова можете объединить send с class_eval...

Есть множество способов, я думаю:)

Ответ 3

Одиночные методы объекта

instance_eval

class A
end

a = A.new

a.instance_eval do
def v 
"asd"
end
end

 a.singleton_methods
 => [:z, :v]