Ruby 3.0. Ruby i mniej znane metody kontroli prywatności
Tomasz Szkaradek
Architekt rozwoju
Jedną z najbardziej lubianych cech Rubiego jest jego bardzo elastyczna składnia. Osobiście uwielbiam Rubiego za to, jak wiele możliwości mamy w definiowaniu klas i ich właściwości, i to właśnie omówię w tym artykule.
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
Sukces! Nasza metoda baz stała się publiczna, ponieważ uwidoczniliśmy ją dwukrotnie. Oczywiście ta sama operacja dotyczy modułów. Świetnie, ale dokąd nas to zaprowadzi? 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, co Ruby 2.7 może zrobić w zakresie zmiany widoczności 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?
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
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.