Ruby - Путаница с методом массива

мы можем вызвать метод Array на верхнем уровне следующим образом

Array(something)

для меня это имеет смысл, это вызов метода без явного получателя, а self, который в данном случае является основным, вставляется перед вызовом метода. Но разве это не эквивалентно:

Kernel.Array(something)

это не имеет для меня смысла. Поскольку в первом случае объект main относится к классу Object, к которому примешан модуль ядра, то есть метод Array. Но во втором случае мы вызываем метод Array для самого объекта модуля ядра, а не для основного объекта, разве это НЕ одно и то же?

Извините за мой плохой английский.


person freenight    schedule 06.12.2009    source источник


Ответы (4)


Kernel.Array — это то, что известно как функция модуля. Другими примерами модульных функций являются Math.sin, Math.hypot и так далее.

Функция модуля — это метод, который одновременно является методом класса модуля и частным методом экземпляра. Когда вы вызываете Array() на верхнем уровне, вы вызываете его как частный метод экземпляра основного объекта. Когда вы вызываете его через Kernel.Array(), вы вызываете его как метод класса в ядре. Это один и тот же метод.

Чтобы узнать больше, прочитайте о методе module_function в rubydocs: http://www.ruby-doc.org/core/classes/Module.html#M001642

person horseyguy    schedule 06.12.2009
comment
+1 за то, что выглядит очень полезным объяснением. Не могли бы вы указать/объяснить разницу в документации, упомянутой в моем ответе? - person Carl Smotricz; 06.12.2009
comment
@Карл, какую документацию ты читаешь? но это правда, что многие документы ruby ​​оставляют желать лучшего - person horseyguy; 06.12.2009
comment
ruby-doc.org/core/classes/Array.html› и ‹ruby-doc.org/core/classes/Kernel.html›. Лошадиная пасть, так сказать. Я думаю, что rdoc мог бы использовать какой-то механизм для автоматизации этих преднамеренных идентичных дубликатов. - person Carl Smotricz; 06.12.2009

class Object смешанный модуль Kernel, но Kernel является экземпляром Object. Итак, методы "модуля" ядра - это методы экземпляра.

person andrykonchin    schedule 06.12.2009
comment
это не может быть правильным, потому что метод Array является частным методом экземпляра и поэтому не будет доступен непосредственно в ядре. Попробуйте на любом другом объекте => Object.new.Array #=> ошибка приватного метода - person horseyguy; 06.12.2009
comment
да, вы правы - в Object его частный метод экземпляра (но в ядре его общедоступный). Я не вижу никакого варианта, кроме класса ‹‹ Публичное ядро: конец массива - person andrykonchin; 06.12.2009
comment
к вашему сообщению. Когда вы вызываете его через Kernel.Array(), вы вызываете его как метод класса в ядре. Это один и тот же метод. В документации метод Array является методом публичного экземпляра ядра, и проблема заключается в том, как он становится методом общедоступного класса ядра... - person andrykonchin; 06.12.2009

Что вас смущает, так это разница между методами класса и экземпляра.

Методы класса не имеют явного получателя и, следовательно, не имеют self для доступа к другим полям. Они просто... есть.

Обычно методы экземпляра используются для запроса или управления атрибутами данного объекта, тогда как методы класса являются «вспомогательными» или «фабричными» методами, которые предоставляют некоторые функции, связанные с классом определенного типа или особенно полезные для него, но не зависящие от фактического живые экземпляры (объекты) этого класса.

Не уверен насчет Ruby, но в Java есть (например) целый класс Math, который не содержит ничего, кроме методов экземпляра, таких как sin(), max(), exp() и т. д.: объекта «Math» нет, это просто методы, воплощающие математические алгоритмы. Не лучший пример, потому что в Ruby эти методы, вероятно, встроены прямо в числовые классы как методы экземпляра.

Случай, который вы упомянули, немного сбивает с толку, потому что метод () Array и метод Array() Kernel на самом деле являются разными методами, которые делают похожие вещи. Оба являются методами класса.

Array() принимает список аргументов, создает и возвращает содержащий их массив.

Kernel.Array() принимает один аргумент "массивного" типа, такого как последовательность, принимает значения, возвращаемые этим аргументом, и строит из них массив.


ОБНОВЛЕНИЕ

Понижение, возможно, было оправдано; Приношу свои извинения за то, что затрагиваю тему, не входящую в мою компетенцию. Я думаю, что скоро удалю этот ответ.

@ Чак: Я искренне надеюсь, что официальная документация по языку/библиотеке предложит некоторые важные подсказки о том, как это работает. Это то, с чем я консультировался, отвечая на этот вопрос.

Rdoc для Kernel.Array():

Возвращает arg в виде массива. Сначала пытается вызвать arg.to_ary, затем arg.to_a. Если оба терпят неудачу, создает массив из одного элемента, содержащий arg (если только arg не равен нулю).

для Array.():

Возвращает новый массив, заполненный заданными объектами.

Не знаю, как вы, но я думаю, что если документы так сильно различаются, то либо они говорят об отдельных методах, либо документация — это крушение поезда.

@ свободный рыцарь:

Но в ruby ​​все является объектом, даже классы и модули. А Kernel.Array на самом деле является вызовом метода для конкретного объекта — объекта ядра.

Да, под обложками это похоже и на Java. Но метод Array() ничего не делает с ядром, так же как Array() ничего не делает с объектом класса Array, так что на самом деле это всего лишь семантическая придирка. Это метод экземпляра, потому что вы могли бы повесить его на класс IPSocket, если бы были достаточно сумасшедшими, и он все равно работал бы так же.

person Carl Smotricz    schedule 06.12.2009
comment
Получателем методов класса является одноэлементный класс, представляющий класс. - person R. Martinho Fernandes; 06.12.2009
comment
В общем, метод класса действительно является чем-то вроде фабрики или помощника, и это особенно верно в Java. Но в ruby ​​все является объектом, даже классы и модули. А Kernel.Array на самом деле является вызовом метода для конкретного объекта — объекта ядра. - person freenight; 06.12.2009
comment
Другими словами, внутри методов класса есть self. Кроме того, я не вижу доказательств того, что два Array() являются разными методами, и ни один из них не является методом класса. - person Chuck; 06.12.2009
comment
Чак, Array - это module_function (как указано в моем ответе), а также метод класса в ядре, а также метод частного экземпляра в ядре. (для доказательства проверьте определение rb_define_global_function в class.c) - person horseyguy; 06.12.2009
comment
@ Мартиньо, это неправильно. Получателем метода класса является КЛАСС. Однако метод класса должен быть определен в синглтоне класса. - person horseyguy; 06.12.2009
comment
Еще несколько уточнений в моем ответе. Обсуждение в комментариях становится настолько интересным, что было бы стыдно удалить ответ; любые (не непристойные) предложения относительно того, что я должен делать? - person Carl Smotricz; 06.12.2009

Это одно и то же:

a = Kernel.Array('aa')
=> ["aa"]
a.class
=> Array
a = Array('aaa')
=> [" aaa"]
a.class
=> Массив

Может есть псевдоним?

person VP.    schedule 06.12.2009