2013-11-18 1 views
3

Я читал, что «puts» - это частный метод экземпляра модуля Kernel (и, следовательно, Object, поскольку Object смешивает в ядре).Если метод «puts» является методом частного экземпляра, почему мы можем его вызвать из любого места?

Именно поэтому, когда мы вызываем puts, мы не указываем явный приемник. Мой вопрос: если это метод частного экземпляра, как это возможно, мы можем назвать его из любой другой области? Итак, мы можем сделать:

class Test 
    puts "hello" # self is Test. So, we are calling self.puts "hello" - 
end 

Что мне здесь не хватает? Как это возможно? Мы вызываем метод частного экземпляра?

EDIT: возникает

Тот же вопрос, если я это сделать:

class Object 
    private 
    def talk 
    puts "hi there" 
    end 
end 

class Test 
    talk # outputs 'hi there' 
end 

Почему возможно, что из класса Test мы можем назвать частный метод из класса Object?

+0

Где вы прочли это частный метод? Это не. Это даже не метод экземпляра, поскольку ядро ​​- это модуль, а не класс. Доказательство: 'Kernel.puts" Доказательство ". – Amadan

+0

Потому что вся программа Ruby на самом деле происходит в контексте экземпляра класса 'Object' (не уверен, поэтому я поставил комментарий, а не ответ). –

+1

«puts and print - встроенные методы частных экземпляров ядра - не как те, которые вы пишете, Объекта, а ядра». - Rubyist 1.9 - The Well Grounded Rubyist ... –

ответ

3

Пожалуйста, посмотрите документ для модуля ядра - http://www.ruby-doc.org/core-2.0.0/Kernel.html.

В отличие от Java, Ruby не ограничивается классами как контейнеры реализаций. Модули действуют как замечательные контейнеры, которые могут быть смешаны с другими классами. Когда модуль перемещается в другой класс, все его методы экземпляра становятся экземплярами этого класса. Поскольку модуль Kernel смешан с классом Object, его методы доступны во всех классах Ruby.

Пожалуйста, прочтите следующее:

  1. Ruby access control
  2. Common misunderstanding and clarification about access controls in Ruby

С риском дублирования, я должен сказать следующее: private в Руби не то же самое, как и в C++ или Java , Подклассы класса могут вызывать частные методы, объявленные в их суперклассе. Фактически, вы можете вызвать частный метод любого класса, используя :send. Единственная разница между частными и защищенными методами заключается в том, что частные методы нельзя вызывать с явными приемниками.

Даже последнее правило имеет исключение. Если ваш частный метод - это что-то вроде age=, он может (и должен быть) вызван с self. Смешно, не так ли? :)

UPDATE: (объяснить суть):

Метод talk который вы написали в вашем коде выше вызывается на main объекта, который является контекстом для всех программ на Ruby. Он не называется в классе Test, поэтому он не работает для вашего второго аспекта.

В сущности, которую я предоставил, talk - метод частного класса, поэтому он запускается во время определения класса. В том же самом способе метод talk2 является методом экземпляра и может быть вызван только из методов экземпляра. Ваш пример gist не работал, потому что вы пытались вызвать метод экземпляра во время определения класса.

+0

Я отредактировал свой вопрос с другим примером, потому что я думаю, что не достаточно объяснил свои сомнения. –

+0

Пожалуйста, прочитайте [это] (http://www.skorks.com/2010/04/ruby-access-control-are-private-and-protected-methods-only-a-guideline/), в то время как я обновляю ответ с помощью больше ссылок и разъяснений. – Chandranshu

+0

Спасибо за ответ, но я до сих пор не понимаю, в чем разница между этими двумя: https://gist.github.com/anonymous/7523457 и https://gist.github.com/anonymous/7523614 - Можно было бы добавить строку, а другую - к ошибке Undefined method. –

0

Я не понимаю, почему такой длинный ответ, как в другом ответе, требуется или поддерживается.Ответ на ваш вопрос прост.

Это потому, что почти все классы (то есть ничего, кроме BasicObject) содержит Kernel. Поэтому в рамках обычного объекта класс наследуется, и, следовательно, его методы доступны. Вот и все.

Смежные вопросы