2015-02-18 4 views
2

(отредактировано, чтобы сделать вопрос более специфичным)Ruby: выполнить одноплодный метод в другом контексте

Я хотел бы знать, если это возможно, чтобы выполнить одноплодный метод в контексте другого объекта, как показан в следующем примере:

class A 
    def initialize 
    @foo = 'foo' 
    end 
end 

def A.singleton(*args) 
    puts 'in singleton' 
    puts @foo 
end 

A.new.instance_eval &A.method(:singleton) 

# output is: 
# - in singleton 

# desired output: 
# - in singleton 
# - foo 
+0

Не могли бы вы объяснить, почему вы используете эту запутанную структуру? Я не могу придумать никаких причин, по которым определение метода singleton в модуле приведет к тому, что метод экземпляра будет определен в охватывающем модуле. Если мы знаем пример использования, мы можем показать вам более идиоматический подход. – Max

+0

Это эксперимент и чисто синтаксический способ, позволяющий группировать или добавлять дополнительные функции к определенным методам. Я ценю более идиоматический способ использования метода класса, например, 'special_method: baz' и т. Д., Но я просто изучал альтернативный подход. Возможным приложением может быть memoize метод таким образом, то есть 'def memoize.baz', но я согласен, что это запутывает и, вероятно, не то, что я буду использовать в реальном проекте. Мне все равно было бы интересно узнать, возможно ли это. – coxy

ответ

0

Это невозможно. На самом деле Руби имеет определенную ошибку, когда вы попытаетесь сделать это:

module Foo 
    def self.bar 
    end 
end 

class Baz 
end 

Foo.method(:bar).unbind.bind(Baz.new) 
# TypeError: singleton method called for a different object 

Это действительно является искусственное ограничение, так как UnboundMethod#bind легко может просто пропустить проверку типа и позволяют это сделать. Но было бы принципиальным противоречием, если бы вы могли назвать метод singleton с другим приемником: один метод singleton определен для одного экземпляра. Имеет смысл, что это запрещено.

+0

ОК, признавая, что это невозможно. Благодаря! – coxy

0

Я не думаю, что это возможно. A::Singletons, по иронии судьбы, сам по себе одиночный (в смысле шаблона Синглтона), и так, поскольку в системе есть только один A::Singletons, но A может быть include деактивирован во многих разных модулях, нет никакого способа узнать в который модуль для добавления метода.

+0

Спасибо Jörg. Возможно, тогда это невозможно. Хотя я все-таки приблизился (думаю), я обновил этот пример. Метод 'instance_exec' вызывает метод' baz' (проверяется с помощью операторов puts), но он не печатает значение '@ bar' – coxy

+0

Это возможно обойти это, используя анонимные модули вместо' A :: Singletons', но даже тогда вы сталкиваетесь с ошибкой, упомянутой в моем ответе. – Max