La situación: Tengo varias clases que debe contener cada una variable con un hash de configuración; un hash diferente para cada clase pero igual para todas las instancias de una clase.Ruby: Heredar código que funciona con variables de clase
Al principio, traté como esto
class A
def self.init config
@@config = config
end
def config
@@config
end
end
class B < A; end
class C < A; end
Pero pronto se dio cuenta de que no iba a funcionar de esa manera porque @@ configuración se lleva a cabo en el contexto de A, no B o C, por lo tanto:
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"
pensé en usarlo como esto:
modules = [B, C]
modules.each do |m|
m.init(@config[m.name])
end
# ...
B.new # which should then have the correct config
Ahora, es claro para mí por qué sucede esto, pero no estoy seguro acerca º La razón por la cual es así.
¿No podría funcionar a la inversa, manteniendo la variable de clase en el contexto de la subclase?
Lo que también encontré irritante fue el hecho de que el yo siempre es la subclase incluso cuando se llama 'en' la superclase. A partir de esto, primero esperaba que el código de la superclase se "ejecutara en el contexto de" la subclase.
Algunos iluminación sobre este sería muy apreciada.
Por otro lado, probablemente tenga que aceptar que funciona de esa manera y que tengo que encontrar otra manera de hacerlo.
¿Hay una manera "meta" para hacer esto? (Lo intenté con class_variable_set etc. pero sin suerte)
¿O tal vez la idea de ese método 'init' es defectuosa en primer lugar y hay algún otro "patrón" para hacer esto?
Podría simplemente hacer @@ config un hash, manteniendo todas las configuraciones y elegir siempre la correcta, pero me parece un poco incómodo ... (¿no hay herencia para resolver este tipo de problema?;)
No veo cómo el diseño es dudoso. Parece una cosa bastante razonable de hacer en general. – Chuck
Eso es exactamente lo que necesitaba saber, ¡muchas gracias! :) Realmente no sé qué más decir, todo está muy claro ahora. El método init estaba destinado a configurar múltiples variables, obtuve el ejemplo de configuración para simplificar. Pero ahora que lo mencionas, es probable que esté aún más limpio con los accesorios;) Nuevamente, ¡muchas gracias! –
@Chuck: por ejemplo, hay un método de instancia ('A # config') que no llama a un método de instancia ni accede al estado de instancia ni se anula. Eso podría ser un artefacto del ejemplo recortado, podría ser un diseño legítimo, pero, tal vez, no lo es. Además, B y C heredan de A, pero no anulan nada, sin embargo, de alguna manera se espera que tengan un comportamiento diferente tanto el uno como el otro, aunque todos sean idénticos. De nuevo: tal vez sensato, tal vez no. Todo depende del contexto, que por supuesto es demasiado pequeño en este ejemplo para llegar a una conclusión sensata. –