Sytuacja: Mam wiele klas, które powinny posiadać zmienną z hashem konfiguracyjnym; inny skrót dla każdej klasy, ale taki sam dla wszystkich instancji klasy.Ruby: Dziedzicz kod działający ze zmiennymi klasy
Początkowo starałem się ten
class A
def self.init config
@@config = config
end
def config
@@config
end
end
class B < A; end
class C < A; end
Wkrótce jednak zauważyć, że to nie działa w ten sposób, ponieważ @@ config odbywa się w kontekście A, B lub C nie, a więc:
B.init "bar"
p B.new.config # => "bar"
p C.new.config # => "bar" - which would be nil if B had it's own @@config
C.init "foo"
p B.new.config # => "foo" - which would still be "bar" if C had it's own @@config
p C.new.config # => "foo"
Myślałem o użyciu go tak:
modules = [B, C]
modules.each do |m|
m.init(@config[m.name])
end
# ...
B.new # which should then have the correct config
teraz jest dla mnie jasne, dlaczego tak się dzieje, ale nie jestem pewien o TH Powód, dla którego tak jest.
Czy to nie działa również w drugą stronę, trzymając zmienną klasy w kontekście podklasy?
To, co uważałem za irytujące, to fakt, że self jest zawsze podklasą, nawet gdy jest nazywana "w" superklasą. Z tego, po pierwsze, spodziewałem się, że kod z superklasy jest "wykonany w kontekście" podklasy.
Niektóre oświecenia na ten temat byłyby bardzo cenne.
Z drugiej strony, prawdopodobnie muszę zaakceptować to działa w ten sposób i że muszę znaleźć inny sposób, aby to zrobić.
Czy istnieje sposób "meta" to zrobić? (Próbowałem z class_variable_set itp. Ale bez powodzenia)
A może to jest cała idea tej metody "init" wadliwej na pierwszym miejscu i jest jakiś inny "wzór", aby to zrobić?
Mogę tylko zrobić @@ config hash, trzymając wszystkie konfiguracje i zawsze wybrać właściwą, ale uważam, że trochę niezręczne .. (nie jest tam dziedziczenie, aby rozwiązać ten rodzaj problemu?;)
Nie widzę, jak wzór jest niepewny. Wydaje się, że jest to dość rozsądna rzecz do zrobienia w ogóle. – Chuck
Dokładnie to musiałem wiedzieć, dziękuję bardzo! :) Naprawdę nie wiem, co jeszcze powiedzieć, teraz wszystko jest tak jasne. Metoda init była przeznaczona do ustawiania wielu zmiennych, mam na przykład konfigurację dla uproszczenia. Ale teraz wspomnij o tym, prawdopodobnie nadal jest czystszy z akcesoriami;) Jeszcze raz bardzo dziękuję! –
@Chuck: Na przykład istnieje metoda instancji ('A # config'), która nie wywołuje metody instancji, nie uzyskuje dostępu do stanu instancji ani nie zostaje nadpisana. To może być artefakt z przyciętego przykładu, może to być uzasadniony projekt, ale może nie jest. Również B i C dziedziczą z A, ale niczego nie przesłonią, jednak oczekuje się, że będą mieć różne zachowania zarówno od siebie nawzajem, jak i od A, mimo że wszystkie są identyczne. Znowu: może rozsądny, może nie. Wszystko zależy od kontekstu, który oczywiście jest o wiele za mały w tym przykładzie, aby dojść do rozsądnych wniosków. –