Ruby: Dziedzicz kod, który działa ze zmiennymi klasy
Sytuacja: Mam wiele klas, z których każda powinna zawierać zmienną z hashem konfiguracji; inny skrót dla każdej klasy, ale taki sam dla wszystkich instancji klasy.
Na początku próbowałem tak
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łem, że nie będzie działać w ten sposób, ponieważ @@ config odbywa się w kontekście A, nie B lub C, a zatem:
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"
Pomyślałem o użyciu tego w ten sposób:
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, dlaczego tak jest.
Czy nie może też działać w inny sposób, trzymając zmienną klasy w kontekście podklasy?
Irytujące było również to, że jaźń jest zawsze podklasą, nawet gdy jest nazywana „w” nadklasą. Na tej podstawie po raz pierwszy oczekiwałem, że kod z nadklasy zostanie „wykonany w kontekście” podklasy.
Pewne oświecenie na ten temat byłoby bardzo mile widziane.
Z drugiej strony prawdopodobnie będę musiał to zaakceptować i muszę znaleźć inny sposób, aby to zrobić.
Czy istnieje „meta” sposób na to? (Próbowałem z class_variable_set itp., Ale bez powodzenia)
A może cały pomysł tej metody „init” jest w pierwszej kolejności wadliwy i istnieje jakiś inny „wzór”, aby to zrobić?
Mogłem po prostu zrobić @@ config hash, trzymając wszystkie konfiguracje i zawsze wybrać właściwy, ale uważam, że jest to trochę niezręczne ... (czy dziedziczenie nie rozwiązuje tego rodzaju problemu?;)