(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-5LHNRP9'); thecodest, Autor na The Codest - Strona 13 z 13

Podstawowe rozwiązania

Załóżmy, że używamy klasy Foo, która ma jedną metodę publiczną i jedną prywatną:

klasa Foo
  def bar
    :awesome
  end

  prywatny

  def baz
    something_private
  end
end

Wszystko świetnie, widzimy takie rozwiązanie praktycznie w każdym projekt. Bieganie Foo.new.baz spowoduje błąd NoMethodError (prywatna metoda 'baz' wywołana dla #) i to właśnie chcieliśmy zrobić. Co się stanie, jeśli spróbujemy zmienić format zapisu i dodamy private jako przedrostek w definicji klasy?

klasa Foo
  def bar
    :awesome
  end

  private def baz
    :something_private
  end
end

Jak widać po uruchomieniu kodto faktycznie działa! Dlaczego możemy wprowadzić widoczność metody przed jej wykonaniem? Ponieważ podczas definiowania metody, def zwraca nazwę metody jako symbol. Wyrażenie to jest nie tylko częścią składni, ale de facto metodą wywodzącą się z klasy Module i traktującą ten symbol jako argument. Więcej informacji można znaleźć w dokumentacji w tym linku. Skoro zaczęło się tak łatwo od private, spróbujmy zmienić widoczność metody prywatnej.

klasa Foo
  def bar
    :awesome
  end

  private def baz
    :something_private
  end

  public :baz
end

Co się stanie po uruchomieniu kodu?

irb(main):012:0> Foo.new.baz
=> :something_private

Sukces! Nasza metoda baz stała się publiczna, ponieważ uwidoczniliśmy ją dwukrotnie. Oczywiście ta sama operacja dotyczy modułów.

Świetnie, ale skąd to się bierze? my?

Ta funkcjonalność daje nam wiele, ponieważ możemy dowolnie zmieniać widoczność metody podczas jej definiowania, a nawet zmieniać widoczność metod podczas ich dziedziczenia.

Przyjrzyjmy się teraz temu, co Ruby 2.7 może zmienić widoczność aliasów i akcesorów.

class Foo
  private attr_accessor :awesome_variable
end

Niestety, otrzymujemy błąd, ponieważ metoda prywatna oczekuje symboli i attr_accessor. Kod zwraca nil, a zatem ta metoda nie jest zgodna z prywatnym użyciem w Ruby 2.7. Jakie więc mamy opcje?

  1. Możemy użyć attr_accessor pod słowem kluczowym private, aby to zadziałało, tj. otrzymamy błąd, gdy będziemy chcieli odwołać się do awesome_variableawesome_variable metoda.
class Foo
  prywatny

  attr_accessor :awesome_variable
end
  1. Drugą opcją jest wykonanie metody prywatnej na metodach wygenerowanych przez attr_attributeW tym przypadku musimy również pamiętać o wpisaniu tam settera.
class Foo
  attr_accessor :awesome_variable

  private :awesome_variable, :awesome_variable=
end

Problemy z attr_ * nie są jedynymi przeszkodami. Tę samą trudność możemy napotkać, gdy chcemy utworzyć prywatny alias.

class Foo
  private alias :bar, :awesome_bar
end

Ruby 3.0 i nasza działalność

Na szczęście Ruby 3.0 wprowadza świetną zmianę, ponieważ metody widoczności mogą przyjmować tablicę jako argument, a alias metod, attr_ *, może zresetować tablicę z nazwami metod, które zostały zdefiniowane. Możesz przeczytać więcej tutaj.

Zobaczmy teraz kilka przykładów w najnowszym euba i sprawdźmy, czy zmiany zostały faktycznie wprowadzone i jak możemy z nich korzystać.

W pierwszym przykładzie użyjmy private przed attr accessor:

class Foo
  private attr_accessor :awesome_variable
end

Takie wywołanie nie spowoduje błędów w parsowaniu składni i, co ważne, nie spowoduje błędów w działaniu funkcji awesome_variable iawesome_variable =metody stają się prywatne.

Metoda aliasu zrobi to samo, ale teraz również zwraca symbol jako nazwę nowej metody i czyni ją widoczną.

class Foo
  private alias :bar, :awesome_bar
end

Ciekawostką jest fakt, że możemy również zagłębić się w kolejne metody, np. rewelacyjnąmoduł print może być wywołany pomiędzy private i attrreader; ważne jest, aby taka metoda zwracała tablicę z nazwami metod, które znajdują się po prawej stronie wyrażenia.

class Moduł
  def awesome_print(names)
    puts names
    nazwy
  end
end
class Foo
  private awesome_print attr_reader :awesome_bar
end 

Podsumowanie

Mamy nadzieję, że ten artykuł okaże się przydatny! W przypadku dalszych wiadomości o Ruby 3.0. czytaj dalej tutaj.

Szczęśliwego kodowania!

Oferta dla programistów Ruby

Czytaj więcej:

Zamknij się i bierz swoje pieniądze #1: Ukryte koszty i prawdziwa elastyczność w procesie rozwoju produktu

Wyzwania CTO - skalowanie i rozwój oprogramowania

pl_PLPolish