Где методы определены на верхнем уровне ruby?

На верхнем уровне определение метода должно приводить к закрытомуObjectи тесты, кажется, подтверждают это:

def hello; "hello world"; end

Object.private_instance_methods.include?(:hello) #=> true
Object.new.send(:hello) #=> "hello world"

Тем не менее, следующее также работает на верхнем уровне (self.meta это собственный классmain):

self.meta.private_instance_methods(false).include?(:hello) #=> true

Похоже, чтоhello метод определяется одновременно на собственном классе главного иObject, В чем дело? Обратите внимание, чтоfalse параметр дляprivate_instance_methods исключает методы суперкласса из списка методов.

 horseyguy19 нояб. 2009 г., 07:42
@ Эндрю, извините, это ruby 1.9
 horseyguy19 нояб. 2009 г., 07:21
короткая рука для класса << self; самостоятельно; конец
 Slipp D. Thompson09 апр. 2012 г., 15:54
Если это Ruby 1.9, почему бы не сделать вещи более понятными и использоватьself.singleton_class?

Ответы на вопрос(1)

Решение Вопроса

это поведение и лежащие в его основе рассуждения существовали всегда; В 1.9 нет ничего нового. Техническая причина, по которой это происходит, заключается в том, чтоmain является особенным и рассматривается иначе, чем любой другой объект. Там нет никакого причудливого объяснения: он ведет себя так, потому что он был разработан таким образом.

Хорошо, но почему? В чем причинаmain быть волшебным? Потому что дизайнер Ruby Юкихиро Мацумото так думаетделает язык лучше иметь такое поведение:

Поэтому методы верхнего уровня не создают синглтон-методы для этого объекта, вместо того, чтобы использовать их как методы экземпляра для самого класса Object (и, следовательно, во всех других классах, т. Е. Загрязнение пространства имен больше, чем обычно предполагается). Это все еще позволило бы методам верхнего уровня вызывать другие методы верхнего уровня. И если объект верхнего уровня упоминается некоторой константой, такой как Main, то эти методы можно вызывать из любого места с помощью Main.method (...).

Вы действительно хотите печатать "Main.print" везде?

Далее в обсуждении он объясняет, что он ведет себя так, потому что он чувствует, что «предположение естественно».

РЕДАКТИРОВАТЬ:

В ответ на ваш комментарий ваш вопрос направлен на то, почему собственный класс main, кажется, сообщаетhello как частный метод экземпляра. Уловка в том, что ни одна из функций верхнего уровня на самом деле не добавлена вmain, но прямо кObject, При работе с собственными классамиinstance_methods Семейство функций всегда ведет себя так, как будто собственный класс все еще является исходным классом. То есть методы, определенные в классе, обрабатываются как определенные непосредственно в собственном классе. Например:

class Object
  private
  def foo
    "foo"
  end
end

self.send :foo  # => "foo"
Object.private_instance_methods(false).include? :foo  # => true
self.meta.private_instance_methods(false).include? :foo  # => true

class Bar
  private
  def bar
    "bar"
  end
end

bar = Bar.new
bar.send :bar  # => "bar"
Bar.private_instance_methods(false).include? :bar  # => true
bar.meta.private_instance_methods(false).include? :bar  # => true

Мы можем добавить метод непосредственно вmainСобственный класс, хотя. Сравните ваш оригинальный пример с этим:

def self.hello; "hello world"; end

Object.instance_methods.include? :hello  # => false
self.meta.instance_methods.include? :hello  # => true

Хорошо, но что, если мы действительно хотим знать, что данная функция определена в собственном классе, а не в исходном классе?

def foo; "foo"; end  #Remember, this defines it in Object, not on main
def self.bar; "bar"; end  #This is defined on main, not Object

foo  # => "foo"
bar  # => "bar"

self.singleton_methods.include? :foo  # => false
self.singleton_methods.include? :bar  # => true
 Slipp D. Thompson09 апр. 2012 г., 15:57
Я тоже немного удивлен этим, но большинство вещей в Ruby поначалу меня удивили. С Руби кажется, что лучшая идеология - жить мечом или умереть от меча.
 horseyguy21 нояб. 2009 г., 05:43
Привет, спасибо: D Тем не менее мне кажется, что ошибка Bar.new.meta.private_instance_methods (false) .include? (: Bar) должна возвращать true для метода, определенного в Bar. Спасибо :)

Ваш ответ на вопрос