Прошу объяснить, как работает self и protected в Ruby?

Здравствуйте, я начинающий программист, у меня возник вопрос с self и protected. Не могу понять, чем protected отличается от private, смотрел на англоязычных форумах, но всё равно ничего не понял, хотелось бы простенький пример. Видел похожий вопрос был связан с Python, но я его, к сожалению, не знаю.

Так же не могу понять, как работает self. Заметил, что иногда используется в методах.

Если быть конкретней, то вот увидел код по колбэкам и не понимаю, зачем тут protected и в методе self.
class User < ActiveRecord::Base
  validates :login, :email, presence: true
  before_validation :ensure_login_has_a_value
  protected
    def ensure_login_has_a_value
      if login.nil?
        self.login = email unless email.blank?
      end
    end
end

Заранее спасибо!
  • Вопрос задан
  • 2143 просмотра
Решения вопроса 1
viktorvsk
@viktorvsk
Public - должны использоваться очень аккуратно. Чем меньше - тем лучше. Это внешнее API для других классов, которые будут его использовать. А чем меньше можно узнать, тем быстрее это можно выучить и запомнить, тем меньше ошибок сделать.

Protected - это те методы, которые доступны потомкам (классам, что наследуют), но не доступны внешним классам. Грубо говоря, удобно, когда вы знаете, что от класса А будут наследовать много-много разных классов, и у этих классов будет один (или много, не важно) общий метод. Который, однако, совершенно не нужен внешним классам. Если бы не было протектеда, было бы 2 пути - сделать метод, который должен быть у всех потомков - публичным. Это плохо, потому что это лишняя информация для внешних классов. Или же - дублировать одинаковые методы в каждом классе потомке. Это плохо, потому что не DRY.

Private - это те методы, который доступны только классу. То есть, грубо говоря, пользоваться ими вы можете только в том же файле, где идет определение класса. Например, удобно ими пользоваться для рефакторинга. Представим, что есть публичный метод, который уже много лет используют 100 разных, неизвестных классов. Но в этом методе - 500 строк. Менять метод нельзя, поэтому вы превращаете его в 10 строк-вызовов приватных методов.

Лучше всего это усвоить, создав разные вариации и попробовав повызывать разные методы. 2 важных вещи, которые нужно помнить в Ruby:
1) Разные ключевые слова для методов класса и экземпляра (private, private_class_method)
2) Если тестируете поведение в консоли с использованием #send, то поведение будет не ООП-шное - #send игнорирует видимость методов

С self все проще. По умолчанию, всегда self подставляется. Метод вызывается сначала для текущего объекта - потом смотрится наличие методов в предке и т.д. и т.д. до объекта Object. Зачем иногда явно пишут self ? Потому что в руби можно создавать методы вида def method=() end; и использовать их с пробелом: method = 2. Для этого, что бы дать понять, что используется именно метод, а не определяется локальная переменная, иногда прибегают к полной записи.

P.S. Если что-то действительно не понятно даже здесь - берите любую книгу по ООП или википедию и пробуйте все в консоли на любом языке программирования, пока не уловите суть.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
Denormalization
@Denormalization
Эх батенька. Это вам основы ООП нужно изучать. Всякие там инкапсуляции, абстракции, полиморфизмы.
Если вам тут объяснят, то вам это ничем не поможет. Вы основ не знаете.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы