Nowości i zmiany w Ruby 1.9 #4 - BasicObject jako klasa podstawowa
4 komentarze | Kategorie: Blog, Techblog | trackbackTagi: 1.9 ruby ruby1.9
Wpis ten jest jedną z części cyklu pt "Nowości i zmiany w Ruby 1.9". Pełną listę wpisów znajdziesz pod adresem http://radarek.jogger.pl/2008/11/30/nowosci-i-zmiany-w-ruby-1-9/.
Kolejną zmianą, o której warto wspomnieć (i przy okazji zapamiętać) jest dodanie klasa bazowej BasicObject dla klasy Object. Do tej pory Object była główną klasą w hierarchi, więc nie miała nadklasy o czym można było się przekonać w taki sposób:
puts Object.superclass
# nil dla Ruby 1.8
# BasicObject dla Ruby 1.9
Ale co jeśli tworzymy własną klasę MyClass? Czy jej nadklasą będzie Object czy BasicObject? Okazuje się, że tu nie zaszła żadna zmiana, tj. klasą bazową pozostała ta pierwsza klasa. Jak zwykle możemy się o tym przekonać bardzo prosto.
class MyClass
end
puts MyClass.superclass
#=> Object w 1.8 i 1.9
Zmiana jest w zasadzie kosmetyczna. O jej celu zaraz napiszę, wcześniej dwa diagramy by łatwiej Ci było zapamiętać nową zmianę (tak na prawdę chciałem sobie narysować diagram).
Hierarchia dziedziczenia w 1.8
Hierarchia dziedziczenia w 1.9
Po co kolejna nadklasa?
Na pierwszy rzut oka zmiana wydaje się dziwna, w końcu wciąż domyślnie dziedziczymy z Object i jest to jedyna klasa dziedzicząca z BasicObject. Sęk w tym, że nie ma żadnej przeszkody by utworzyć klasę dziedziczącą właśnie z tej nowej klasy. Ta klasa powstała by zapewnić możliwość utworzenia klasy z jak najmniejszą liczbą metod, co często się przydaje w tworzeniu wszelakich klas proxy. Jim Weirich tworząc rake nazwał taką "pustą" klasę BlankSlate.
Oto przykładowa implementacja takiej klasy.
class Proxy < BasicObject
def initialize(obj)
@obj = obj
end
def method_missing(sym, *args, &block)
::Kernel.puts "Sending #{sym}(#{args.join(',')}) to obj"
return @obj.send(sym, *args, &block)
end
end
proxy_string = Proxy.new("Ala ma kota")
puts proxy_string.length
proxy_string.reverse!
puts proxy_string
Program wypisuje na wyjściu:
Sending length() to obj
11
Sending reverse!() to obj
Sending respond_to?(to_ary) to obj
Sending to_s() to obj
atok am alA
Zwróć uwagę na ::Kernel.puts. Po pierwsze bez :: nie zostałaby znaleziona stała Kernel. Po drugie wywołanie metody puts musiało zostać określone w taki sposób, gdyż klasa BasicObject nie posiada takiej metody (to z kolei wynika z faktu, że nie miksuje modułu Kernel). Zatem próboa wywołania puts "..." skończyłoby się na nieskończonej rekurencji method_missing. Proste, prawda?
Kolejną zmianę w języku Ruby mamy za sobą. Do następnego razu!
trzeba przyznać, że ciekawe tez miany. Intryguje mnie bardzo jakie zmiany przyniesie ruby 2.0 a i Rails które pojawi sie w okresie wprowadzania nowej wersji języka. A może strach się bać, może znów trzeba będzie gonić a może nic sie nie stanie no cóż zobaczymy.
Jeszcze kilka miesięcy temu na YouTube oglądałem wystąpienie Matz-a w siedzibie Google, w którym mówił (wtedy – może dziś jest inaczej), że problem Rubego 2.0 polega na tym iż nie ma na nią pomysłów, społeczność nie zgłasza zapotrzebowań, programiści nie widzą kierunku zmian czy nazwij to jak chcesz.
Zapotrzebowanie zawsze jest, ale nie zawsze autor jezyka potrafi zaakceptowac zmiany ktore czyjesz ego/widzi misie/wyobraznia moze sobie zarzyczyc.
Jesli chodzi o to co moglo by sie pojawic w 2.0 to np named attributes ktore prawdopodobnie wymagaja pewnych zmian skladni. Potencjalne zmiany w variable scope, w 1.9 variable scope dla blokow zostalo uporzadkowane, ale jest jeszcze kilka miejsce gdzie zachowuje sie to troche dziwnie.
Kolejna z odwaznych zmian moglo by byc pozbycie sie GIL’a, a przezto tez porzucenie kompatybilnosci z modulami pisanymi w c.
Badżok, o ruby 2.0 nie ma co na razie myśleć, myślę, że przyjdzie nam czekać na niego 3-5 lat. 1.9 naprawia i tak najważniejsze bolączki (szybkość, kodowanie). Rozwój języka jest ważny, ale ważne jest także dojrzewanie bibliotek i frameworków. A tutaj codziennie mamy jakieś nowinki :).
Jan, oglądałem ten film i nie przypominam sobie takiej wypowiedzi Matza. Być może muszę przejrzeć go jeszcze raz…