Как получить доступ к (затененной) глобальной функции в рубине

Мне было интересно, как получить доступ к глобальной функции fn в ruby ​​из класса, который также определил метод fn. Я сделал обходной путь, наложив такую ​​функцию:

def fn
end

class Bar
    alias global_fn fn
    def fn
        # how to access the global fn here without the alias
        global_fn
    end
end

Я ищу что-то в строках С++:: для доступа к глобальной области видимости, но я не могу найти никакой информации об этом. Наверное, я не знаю конкретно, что я ищу.

Ответы

Ответ 1

На верхнем уровне a def добавляет частный метод к Object.

Я могу представить три способа получить функцию верхнего уровня:

(1) Используйте send для вызова частного метода непосредственно в Object (работает только в том случае, если метод не является мутатором, так как Object будет приемником)

Object.send(:fn)

(2) Получите экземпляр Method метода верхнего уровня и привяжите его к экземпляру, к которому вы хотите его вызвать:

class Bar
  def fn
    Object.instance_method(:fn).bind(self).call
  end
end

(3) Используйте super (не принимает суперклассы Bar ниже Object переопределяет функцию)

class Bar
  def fn
    super
  end
end

UPDATE:

Так как решение (2) является предпочтительным (на мой взгляд), мы можем попытаться улучшить синтаксис, указав метод утилиты на Object, называемый super_method:

class Object
  def super_method(base, meth, *args, &block)
    if !self.kind_of?(base) 
      raise ArgumentError, "#{base} is not a superclass of #{self}" 
    end

    base.instance_method(meth).bind(self).call(*args, &block)
  end
end

Используйте как показано ниже:

class Bar
  def fn
    super_method Object, :fn
  end
end

Если первый аргумент super_method должен быть допустимым суперклассом Bar, второй аргумент - метод, который вы хотите вызвать, и все остальные аргументы (если они есть) передаются как параметры выбранного метода.