Ruby - przeciążenie nie działa?

Mamy kod na https://github.com/weppos/ruby-4-rails.showoff/blob/master/classes/03_attributes.md :

[code]class Article
@@year = 2011

class << self
# …
end

def year
self.class.year
end
def year(value)
self.class.year = value
end
end

a = Article.new
a.year

=> 2011

a.year = 2012
Article.year

=> 2012[/code]

Kod ten zwróci błąd:
:in `year’: wrong number of arguments (0 for 1) (ArgumentError)

Pytanie: dlaczego Ruby nie przeciąża metody? Czy nie powinien uznawać te dwie metody za różne (w zależności od argumentów) ?

Pozdrawiam! :slight_smile:

Min. dlatego, że nie jest statycznie typowany. Ale można robić bogate sygnatury metod min. poprzez hashe, dobrym przykładem jest ActiveRecord::Base.find.
Jest o tym sporo artykułów, np:

Pozatym, jak tworzysz setter, to powinieneś napisać tak:

def year=(value) self.class.year = value end

@slawosz - wiem że setter jest tak robiony, ale mimo wszystko, czysto teoretycznie pytałem, czemu nie działa, choć w moim odczuciu powinno :slight_smile:

Zasadniczo hash jest okey, można też założyć nieokreśloną liczbę argumentów, ale dziwił mnie fakt, że nie możńa zwyczajnie w świecie przeciążyć funkcji bez żadnych bajerów, w końcu zdarza się, że w zależności od parametrów jest zupełnie inny kod.

Taka jest filozofia Rubiego. Zasadniczo - w językach statycznie typizowanych przeciążanie jest uzasadnione - bo możesz określić przez hierarchię typów, która metoda ma być wywołana.
W Rubim i innych j. dynamicznie typizowanych teoretycznie można by wywoływać różne metody w zależności do ilości parametrów, ale biorąc pod uwagę argumenty opcjonalne, szybko prowadziłoby to do niejednoznaczne i niezrozumiałego kodu.

Wyobraź sobie taki scenraiusz: masz metodę z jedym i dwom argumentami (najlepiej w klasie nadrzędnej i podrzędnej). A potem (przez pomyłkę) do tej z jednym dodajesz opcjonalny i przez pół dnia szukasz błędu.

Podsumowując: less is more.

Przekonałeś mnie ; )

Można zamknąć.

Była o tym ciekawa dyskusja na rupy :slight_smile:

właściwie można by rozwiązanie wprowadzić, definiująć metodę w postaci def overload.method(x), def overload.method(x, y), wówczas w przypadku próby nadpisania metody wyrzucałby błąd, a żeby zmienić definicje trzeba by również zastosować specjalną metodę przyjmującą jako blok kod nowej metody, jednocześnie pozwalając stworzyć metody przeciązone, co o tym myślicie?

paneq - móglbyś podzielić się krótkim streszczeniem ? ; >

Pewnie, można wszystko. Pytanie tylko, czy ma sens przenoszenie konstrukcji z języka statycznie typizowanego do języka dynamicznego? Nowy język to nie tylko nowa składnia, ale też nowe podejście.

Przeciążanie funkcji jest zaprzeczeniem prawa jednej odpowiedzialności. Metoda powinna spełniać jedno zadanie.

Edit: podaj może inny przykład, gdzie uważasz, że przeciążanie metod jest niezbędne/najbardziej eleganckie.