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

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

Okładka posta: Klasa Singleton (eigenclass) w Ruby: co to jest i po co to potrzebne
Spis treściKliknij link, aby przejść do wybranego miejsca
Ta treść została automatycznie przetłumaczona z ukraińskiego.
W Ruby wszystko jest obiektem (no, prawie wszystko), nawet klasy. I każdy obiekt może mieć własne unikalne metody, które nie należą do innych instancji tej samej klasy.
Czym jest Proc i Lambda przeczytaj w moim poprzednim wpisie.
Te metody są przechowywane nie w zwykłej klasie, ale w specjalnej ukrytej klasie, która nazywa się singleton class lub eigenclass.

Czym jest singleton class?

Singleton class to "osobista" klasa konkretnego obiektu. To tam Ruby przechowuje metody, które są zdefiniowane tylko dla tego obiektu.
user1 = "Alice"
user2 = "Bob"

def user1.greet
  "Hello, I'm #{self}!"
end

p user1.greet  # => "Hello, I'm Alice!"
p user2.greet  # => NoMethodError
Tutaj greet to metoda, która istnieje tylko dla obiektu user1.
Ruby stworzył dla user1 jego własną singleton class i umieścił tam tę metodę.

Jak zobaczyć singleton_class?

Każdy obiekt ma metodę singleton_class, która pozwala odwołać się do tej "ukrytej" klasy:
user1.singleton_class
# => #<Class:#<String:0x0000000103c4b8f0>>
Jeśli zdefiniujesz metodę bezpośrednio w tej klasie - również stanie się unikalna:
user = "Ruby"

user.singleton_class.class_eval do
  def version
    "3.2.1"
  end
end

p user.version     # => "3.2.1"

class << self

Kiedy piszesz class << self, w rzeczywistości otwierasz singleton class bieżącego obiektu. To wygodna składnia do definiowania metod wewnątrz niego.
Przykład 1: w zwykłym obiekcie
user = "John"

class << user
  def greet
    "Hi, I'm #{self}"
  end
end

p user.greet  # => "Hi, I'm John"
Przykład 2: w klasie (definiowanie metod klasy)
class Person
  class << self
    def species
      "Human"
    end
  end
end

p Person.species  # => "Human"
Ruby po prostu otworzył singleton class dla samej klasy Person i dodał tam metodę species.
Jeśli krótko:
  • W Ruby każdy obiekt ma swoją własną singleton class - ukrytą klasę dla jego unikalnych metod.
  • Metoda def obj.method lub class << obj dodaje metodę do singleton class tego obiektu.
  • Często używasz tego nieświadomie, gdy piszesz metody klasy (class << self) lub unikalne metody dla jednego obiektu.
Ale dla utrwalenia rozważmy pytanie. Czy można wywołać metodę singleton klasy na jej obiekcie? NIE. Nie będzie dostępna na obiekcie klasy (tj. na instancji).
W przykładzie:
class Person
  class << self
    def species
      "Human"
    end
  end
end
Ruby tworzy metodę klasy, czyli metodę, która żyje w singleton class samej klasy Person, a nie w metodach instancji Person.
Dlatego:
Person.species     # => "Human"
Person.new.species # => NoMethodError
Wyjaśnienie:
  • Person to obiekt klasy Class.
  • class << self otwiera singleton class dla tego obiektu (Person).
  • Metoda species jest tam przechowywana.
  • Instancje Person.new (tworzone obiekty klasy) jej nie widzą, ponieważ szukają metod w zwykłej klasie Person, a nie w jej singleton class.
Jeśli chcesz, aby metoda była dostępna zarówno jako klasowa, jak i instancyjna, możesz po prostu zdefiniować ją dwa razy lub przenieść do modułu:
class Person
  def self.species
    "Human"
  end

  def species
    "Human"
  end
end

Person.species     # => "Human"
Person.new.species # => "Human"
Lub bardziej elegancko - przez moduł:
module Species
  def species
    "Human"
  end
end

class Person
  extend Species   # dodaje metodę jako klasową
  include Species  # dodaje metodę jako instancyjną
end

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

Jak działają tablice w Ruby: praktyczne przykłady each, map, select, inject, reduce, filter_map
28 paź 10:38

Jak działają tablice w Ruby: praktyczne przykłady each, map, select, inject, reduce, filter_map

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
Jak działa self, protected i private (Ruby)
28 paź 13:52

Jak działa self, protected i private (Ruby)

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
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
==, 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
Include, Extend, Prepend w Ruby: jak działają i jaka jest różnica
29 paź 21:20

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

Нотатки про 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