Оволодіння специфікаторами доступу в Ruby (public, protected та private)

pic

Чи замислювалися ви, як працюють контролі доступу, такі як private і protected, у сучасних версіях Ruby?

Я помітив, що багато досвідчених розробників Ruby мають труднощі з поясненням ключових відмінностей між методами private та protected. Щоб пролити світло на це питання, я вирішив написати цю статтю.

Перш ніж заглиблюватися, давайте розглянемо кілька тверджень. Ми визначимо, які з них правильні, а які — ні:

  1. Публічні методи не мають контролю доступу. Їх можна викликати ззовні класу будь-яким екземпляром цього класу.
  2. Як protected, так і private методи не можна викликати ззовні визначеного класу.
  3. Методи protected доступні з підкласів, а методи private — ні.
  4. Методи private класу можна викликати будь-яким екземпляром цього класу.
  5. Публічний доступ є стандартним.

Розуміння специфікаторів доступу з прикладами коду

Давайте розглянемо фрагмент коду, щоб прояснити ці концепції. Зверніть увагу, що наступні приклади застосовуються до сучасних версій Ruby (>=2.7). Ruby 2.7 ввела деякі зміни в поведінку, які я поясню пізніше.

class Example  
 def public_method  
 "Привіт, там"  
 end  

 def invoke_private_method  
 private_method # неявний приймач  
 self.private_method # явний приймач (але все одно self)  
 end  

 def invoke_protected_method  
 protected_method # неявний приймач  
 self.protected_method # явний приймач (але все одно self)  
 end  

 private  

 def private_method  
 puts "Це приватно!"  
 end  

 protected  

 def protected_method  
 puts "Це захищено!"  
 end  
end  

example = Example.new  
example.public_method # => працює; публічний доступ за замовчуванням  
example.invoke_private_method # => працює (нова поведінка в Ruby 2.7 дозволяє це)  

# Вивід  
Це приватно!  
Це приватно!  

example.invoke_protected_method # => працює  

# Вивід  
Це захищено!  
Це захищено!  

example.private_method # => викликає NoMethodError (приватний метод)  
example.protected_method # => викликає NoMethodError (захищений метод)

Інша версія прикладу

Тепер трохи змінимо приклад:

class Example  
 def invoke_private_method(obj)  
 obj.private_method # явний приймач (але не self)  
 end  

 def invoke_protected_method(obj)  
 obj.protected_method # явний приймач (але не self)  
 end  

 private  

 def private_method  
 puts "Це приватно!"  
 end  

 protected  

 def protected_method  
 puts "Це захищено!"  
 end  
end  

example = Example.new  
example.invoke_private_method(example) # => викликає NoMethodError (приватний метод)  
example.invoke_protected_method(example) # => працює  

# Вивід  
Це захищено!

Прояснення спадкування та специфікаторів доступу

Давайте розглянемо деякі поширені непорозуміння щодо спадкування та специфікаторів доступу за допомогою цієї нової версії:

class ChildExample < Example  
 def invoke_private_method_from_child  
 private_method # працює  
 self.private_method # працює  
 end  

 def invoke_protected_method_from_child  
 protected_method # працює  
 self.protected_method # працює  
 end  
end  

child_example = ChildExample.new  
child_example.invoke_private_method_from_child # => працює  
# Вивід  
Це приватно!  
Це приватно!  

child_example.invoke_protected_method_from_child # => працює  
# Вивід  
Це захищено!  
Це захищено!

Це демонструє, що доступ до приватних методів не залежить від спадкування.

Оцінка тверджень

Тепер давайте повернемося до початкових тверджень:

  1. ПРАВДА — Публічні методи не мають контролю доступу.

  2. ПРАВДА — Як protected, так і private методи не можна викликати ззовні визначеного класу.

  3. НЕПРАВДА — Методи protected доступні з підкласів; методи private — ні.

  4. НЕПРАВДА — Приватні методи визначеного класу можуть бути викликані будь-яким екземпляром цього класу.

5.
текст перекладу
TRUE — Загальнодоступність є стандартною.

Примітка: Наведені приклади працюють з Ruby 2.7 або новішими версіями, оскільки до Ruby 2.7 метод self.private_method не був дозволений. У старіших версіях це призводило до помилки NoMethodError. Деталі можна знайти за посиланням зміни в поведінці self

Основні висновки

  1. Приватні методи не можна викликати з явним приймачем, тоді як захищені методи можна.

  2. Приватні методи призначені для використання без явного приймача, щоб забезпечити інкапсуляцію.

  3. Хоча `self.privatemethod`_ працює, це не є конвенційним і слід уникати цього для забезпечення чіткості коду.

Перекладено з: Mastering Ruby Access Specifiers (public, protected & private)

Leave a Reply

Your email address will not be published. Required fields are marked *