Переопределение метода singleton_class, чтобы он вел себя точно так же, как и прежде, а также делал что-то еще - PullRequest
1 голос
/ 21 апреля 2019

Я хочу изменить метод singleton_class определенного класса, чтобы он делал то же, что и раньше, но также делал что-то еще, например, помимо того, что он делал:

  • ставит "привет"

Хорошо, поэтому я знаю, как переопределить обычный метод класса, чтобы фактически делать то же самое, что он делал раньше, но также делать что-то еще, это было бы так:

class Class
   def addHelloToMethod(methodName)
       unboundMethod = instance_method(methodName)

       define_method(methodName) do |*args, &block|

          result =unboundMethod.bind(self).(*args, &block)
          puts "hello"
          result
      end
   end
end

Что мне нужно, так это добавить "привет" к методу singleton_class, поэтому я попробовал это:

class Class
   def addHelloToSingletonClassMethod(methodName)
       unboundMethod = singleton_class.instance_method(methodName)

       singleton_class.define_method(methodName) do |*args, &block|

          result =unboundMethod.bind(self).(*args, &block)
          puts "hello"
          result
      end
   end
end

Что я здесь не так делаю?

Ответы [ 2 ]

1 голос
/ 21 апреля 2019

Один из способов сделать это - добавить анонимный модуль, который переопределяет нужный метод, печатает привет и вызывает super, чтобы вызвать фактическую реализацию.

Я не уверен, почему вы добавляете этот метод в Class. Ваша цель - вызвать addHelloToSingletonClassMethod для экземпляра такого класса, как этот?

irb> s = "foo"
irb> s.addHelloToSingletonClassMethod(:upcase)
irb> s.upcase
hello
=> "FOO"

Если это так, определите следующее для Object:

class Object
   def addHelloToSingletonClassMethod(methodName)
     mod = Module.new
     mod.define_method(methodName) do |*args, &blk|
       puts "hello"
       super(*args, &blk)
     end

     singleton_class.prepend(mod)
   end
end

Или в более типичном для Ruby соглашении об именах:

class Object
  def add_hello_to_method(name)
    mod = Module.new
    mod.define_method(name) do |*args, &blk|
      puts "hello"
      super(*args, &blk)
    end

    singleton_class.prepend(mod)
  end
end

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

irb> String.addHelloToSingletonClassMethod(:upcase)
irb> "foo".upcase
hello
=> "FOO"

тогда вы хотите определить его на Class:

class Class
  def add_hello_to_method(name)
    mod = Module.new
    mod.define_method(name) do |*args, &blk|
      puts "hello"
      super(*args, &blk)
    end

    prepend(mod)
  end
end
0 голосов
/ 21 апреля 2019

Измените изменение addHelloToSingletonClassMethod на self.addHelloToSingletonClassMethod. Это должен быть метод класса.

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