All original content is created in Ukrainian. Not all content has been translated yet. Some posts may only be available in Ukrainian.Learn more
This content has not been translated yet.We're showing the original Ukrainian content below.
У Ruby модулі використовуються для повторного використання коду. Метод додавання модуля впливає на де і як методи з модуля стають доступними.

include - додає методи як методи екземпляра

  • Методи модуля стають доступними для всіх об’єктів класу.
  • Використовують, коли хочуть, щоб методи були у екземплярів класу.
module Greetings
  def hello
    "Hi!"
  end
end

class User
  include Greetings
end

u = User.new
u.hello # => "Hi!"
Методи модуля з’являються у ланцюжку предків класу (ancestors) після самого класу, тобто можна перевизначати їх у класі. Але давайте розберемо це детальніше. У Ruby кожен клас має ланцюжок предків (ancestors) - порядок, у якому Ruby шукає методи при виклику на об’єкті.
module Greetings
  def hello
    "Hi from module"
  end
end

class User
  include Greetings

  def hello
    "Hi from class"
  end
end

p User.ancestors
# => [User, Greetings, Object, Kernel, BasicObject]
Коли ти робиш include Greetings, Ruby вставляє модуль після класу у ланцюжку предків. Або якщо простіше запам'ятати - вище класу.
Це означає, що методи класу перекривають методи модуля, якщо вони мають однакові імена.
u = User.new
u.hello # => "Hi from class"
Ruby спочатку шукає метод у самому класі (User). Потім, якщо не знаходить, перевіряє модулі у ланцюжку (Greetings), далі предків (Object, Kernel).

extend - додає методи як методи класу

  • Методи модуля стають доступними безпосередньо на класі, а не на екземплярах.
  • Зручно для додавання "класових методів" без явного self.method.
module Tools
  def info
    "Class method!"
  end
end

class User
  extend Tools
end

User.info # => "Class method!"
User.new.info # => NoMethodError
Фактично Ruby додає методи в singleton class об’єкта (клас сам по собі - об’єкт).

prepend - додає методи перед класом у ланцюжку предків

  • Методи модуля з’являються перед класом у ланцюжку предків.
  • Це означає, що методи модуля можуть перевизначати методи класу.
module Greetings
  def hello
    "Hello from module"
  end
end

class User
  prepend Greetings

  def hello
    "Hello from class"
  end
end

p User.ancestors
# => [Greetings, User, Object, Kernel, BasicObject]
Ключовий момент: Greetings стоїть перед класом User.
Ruby шукає методи у порядку, який показує ancestors.
Тому коли викликаєш u.hello, Ruby спершу бачить метод у модулі Greetings, а вже потім у класі User.
u = User.new
u.hello # => "Hello from module"
Використання super у модулі
Якщо у модуля викликати super, Ruby піде далі по ланцюжку предків і виконає метод класу:
module Greetings
  def hello
    super + " and module"
  end
end

class User
  prepend Greetings

  def hello
    "Hello from class"
  end
end

u = User.new
u.hello # => "Hello from class and module"
Чому так?
  1. Ruby викликає hello у модулі Greetings (бо він перший у ancestors).
  2. Там є super. Ruby шукає наступний метод у ланцюжку предків, тобто в класі User.
  3. Метод класу повертає "Hello from class", потім додається " and module".

Якщо коротко

include -> методи модуля стають методами екземплярів класу, модуль після класу у ланцюжку предків.
extend -> методи модуля стають методами класу або конкретного об’єкта (singleton class).
prepend -> методи модуля стають методами екземплярів, але перед класом у ланцюжку предків, тобто мають пріоритет над методами класу.

This post doesn't have any additions from the author yet.

Цілочисельне ділення у Ruby: чому 6 / 4 дорівнює 1
28 Oct 14:10

Цілочисельне ділення у Ruby: чому 6 / 4 дорівнює 1

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
28 Oct 14:42

Як працює &:to_s у Ruby і що таке Symbol#to_proc

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
Що таке Proc і Lambda в Ruby?
28 Oct 15:57

Що таке Proc і Lambda в Ruby?

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
Що відбувається, якщо викликати [1, 2, 3].map(&Person)
29 Oct 17:54

Що відбувається, якщо викликати [1, 2, 3].map(&Person)

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
Singleton class (eigenclass) у Ruby: що це і навіщо потрібно
29 Oct 18:29

Singleton class (eigenclass) у Ruby: що це і навіщо потрібно

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
==, equal?, eql?, === у Ruby: що перевіряють і коли використовувати
29 Oct 20:47

==, equal?, eql?, === у Ruby: що перевіряють і коли використовувати

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
module_function у Ruby: коли методи модуля доступні як модульні та як функції
29 Oct 21:53

module_function у Ruby: коли методи модуля доступні як модульні та як функції

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
Що таке memoization в Ruby?
30 Oct 10:17

Що таке memoization в Ruby?

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
is_a?, kind_of?, instance_of? — як Ruby перевіряє тип об’єкта?
30 Oct 19:55

is_a?, kind_of?, instance_of? — як Ruby перевіряє тип об’єкта?

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
&& vs and — різниця в Ruby, яка може зламати ваш код
30 Oct 20:23

&& vs and — різниця в Ruby, яка може зламати ваш код

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
Змінні у Ruby: @, @@ та class instance variable
30 Oct 20:54

Змінні у Ruby: @, @@ та class instance variable

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
Різниця між blank?, present?, empty? та nil? у Ruby
30 Oct 21:06

Різниця між blank?, present?, empty? та nil? у Ruby

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska