Cała oryginalna treść jest tworzona po ukraińsku. Nie wszystkie treści zostały jeszcze przetłumaczone. Niektóre posty mogą być dostępne tylko po ukraińsku.Dowiedz się więcej

Include, Extend, Prepend w Ruby: jak działają i jaka jest różnica

Okładka posta: Include, Extend, Prepend w Ruby: jak działają i jaka jest różnica
Ta treść została automatycznie przetłumaczona z ukraińskiego.
W Ruby moduły są używane do ponownego wykorzystania kodu. Metoda dodawania modułu wpływa na to, gdzie i jak metody z modułu stają się dostępne.

include - dodaje metody jako metody instancji

  • Metody modułu stają się dostępne dla wszystkich obiektów klasy.
  • Używa się, gdy chce się, aby metody były w instancjach klasy.
module Greetings
  def hello
    "Cześć!"
  end
end

class User
  include Greetings
end

u = User.new
u.hello # => "Cześć!"
Metody modułu pojawiają się w łańcuchu przodków klasy (ancestors) po samej klasie, co oznacza, że można je nadpisywać w klasie. Ale przyjrzyjmy się temu dokładniej. W Ruby każda klasa ma łańcuch przodków (ancestors) - kolejność, w jakiej Ruby szuka metod przy wywołaniu na obiekcie.
module Greetings
  def hello
    "Cześć z modułu"
  end
end

class User
  include Greetings

  def hello
    "Cześć z klasy"
  end
end

p User.ancestors
# => [User, Greetings, Object, Kernel, BasicObject]
Kiedy robisz include Greetings, Ruby wstawia moduł po klasie w łańcuchu przodków. Albo jeśli łatwiej zapamiętać - nad klasą.
To oznacza, że metody klasy przesłaniają metody modułu, jeśli mają te same nazwy.
u = User.new
u.hello # => "Cześć z klasy"
Ruby najpierw szuka metody w samej klasie (User). Następnie, jeśli nie znajdzie, sprawdza moduły w łańcuchu (Greetings), a potem przodków (Object, Kernel).

extend - dodaje metody jako metody klasy

  • Metody modułu stają się dostępne bezpośrednio na klasie, a nie na instancjach.
  • Wygodne do dodawania "metod klasowych" bez jawnego self.method.
module Tools
  def info
    "Metoda klasowa!"
  end
end

class User
  extend Tools
end

User.info # => "Metoda klasowa!"
User.new.info # => NoMethodError
Faktycznie Ruby dodaje metody do singleton class obiektu (klasa sama w sobie - obiekt).

prepend - dodaje metody przed klasą w łańcuchu przodków

  • Metody modułu pojawiają się przed klasą w łańcuchu przodków.
  • To oznacza, że metody modułu mogą nadpisywać metody klasy.
module Greetings
  def hello
    "Cześć z modułu"
  end
end

class User
  prepend Greetings

  def hello
    "Cześć z klasy"
  end
end

p User.ancestors
# => [Greetings, User, Object, Kernel, BasicObject]
Kluczowy punkt: Greetings stoi przed klasą User.
Ruby szuka metod w kolejności, którą pokazuje ancestors.
Dlatego gdy wywołujesz u.hello, Ruby najpierw widzi metodę w module Greetings, a potem w klasie User.
u = User.new
u.hello # => "Cześć z modułu"
Użycie super w module
Jeśli w module wywołasz super, Ruby przejdzie dalszym łańcuchem przodków i wykona metodę klasy:
module Greetings
  def hello
    super + " i moduł"
  end
end

class User
  prepend Greetings

  def hello
    "Cześć z klasy"
  end
end

u = User.new
u.hello # => "Cześć z klasy i moduł"
Dlaczego tak?
  1. Ruby wywołuje hello w module Greetings (bo jest pierwszy w ancestors).
  2. Tam jest super. Ruby szuka następnej metody w łańcuchu przodków, czyli w klasie User.
  3. Metoda klasy zwraca "Cześć z klasy", a następnie dodaje " i moduł".

Krótko mówiąc

include -> metody modułu stają się metodami instancji klasy, moduł po klasie w łańcuchu przodków.
extend -> metody modułu stają się metodami klasy lub konkretnego obiektu (singleton class).
prepend -> metody modułu stają się metodami instancji, ale przed klasą w łańcuchu przodków, co oznacza, że mają priorytet nad metodami klasy.

Ten post nie ma jeszcze żadnych dodatków od autora.

Dzielenie całkowite w Ruby: dlaczego 6 / 4 równa się 1
28 paź 14:10

Dzielenie całkowite w Ruby: dlaczego 6 / 4 równa się 1

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

Jak działa &:to_s w Ruby i co to jest Symbol#to_proc

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
Co to jest Proc i Lambda w Ruby?
28 paź 15:57

Co to jest Proc i Lambda w Ruby?

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
Co się stanie, jeśli wywołasz [1, 2, 3].map(&Person)
29 paź 17:54

Co się stanie, jeśli wywołasz [1, 2, 3].map(&Person)

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
Klasa Singleton (eigenclass) w Ruby: co to jest i po co to potrzebne
29 paź 18:29

Klasa Singleton (eigenclass) w Ruby: co to jest i po co to potrzebne

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
==, equal?, eql?, === w Ruby: co sprawdzają i kiedy używać
29 paź 20:47

==, equal?, eql?, === w Ruby: co sprawdzają i kiedy używać

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
module_function w Ruby: kiedy metody modułu są dostępne jako modułowe i jako funkcje
29 paź 21:53

module_function w Ruby: kiedy metody modułu są dostępne jako modułowe i jako funkcje

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
Czym jest memoizacja w Ruby?
30 paź 10:17

Czym jest memoizacja w Ruby?

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
is_a?, kind_of?, instance_of? — jak Ruby sprawdza typ obiektu?
30 paź 19:55

is_a?, kind_of?, instance_of? — jak Ruby sprawdza typ obiektu?

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
&& vs and — różnica w Ruby, która może zepsuć twój kod
30 paź 20:23

&& vs and — różnica w Ruby, która może zepsuć twój kod

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
Zmienne w Ruby: @, @@ oraz zmienna instancji klasy
30 paź 20:54

Zmienne w Ruby: @, @@ oraz zmienna instancji klasy

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
Różnica między blank?, present?, empty? a nil? w Ruby
30 paź 21:06

Różnica między blank?, present?, empty? a nil? w Ruby

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