2010-05-20 12 views
5

¿Cómo puede funcionar esto?Variable de instancia de clase principal de acceso

class A 
    attr_accessor :name 

    def initialize params 
    @name = params[:name] 
    @collection << B.new 
    end 
end 

class B < A 
    def initialize 
    @my_name = lookup_something(<parent.name>) 
    end 
end 

Básicamente, necesito un valor de la clase padre para utilizar en una búsqueda en la clase hija, pero no quieren pasarlo explícitamente si hay una mejor manera. ¿La instancia var del padre es totalmente inaccesible en la clase hija? ¿O se trata de un diseño jerárquico deficiente?

Respuesta

8

que no se sabe muy bien lo que está tratando de hacer aquí - todo el código que ha escrito obras de ejemplo variables. Las variables de instancia son por objeto, no por clase, por lo que no sé a qué se refiere cuando dice "Necesito un valor de la clase principal".

hay varias cosas que observo con su código:

  • clases base deben Nunca estar al tanto de las subclases. Entonces crear objetos B en A#initialize no es algo bueno, porque la base usa la subclase.
  • Está sobrescribiendo la clase B#initialize con un comportamiento completamente diferente que A#initialize. Incluso puede cambiar la lista de parámetros. No es algo muy bueno tampoco. Un objeto de una subclase debe comportarse de la misma manera que un objeto de su superclase.
  • Cuando llama al B.new('myname') la variable @name nunca se asigna, porque nunca se llama al método A#initialize. Tendrá que llamar a cualquiera super(:name => name) (para ejecutar la superclase initialize) o tiene que asignar a @name directamente en B#initialize
  • Una vez que se define @name, todos los métodos de instancia pueden usar su valor. Incluyendo los que están definidos en el padre/superclase.

Déjame decirte que no estoy muy seguro de por qué estás usando la herencia aquí, tengo la sensación de que no es lo que quieres. Si tiene dos clases para dos cosas diferentes, debería nunca ser herencia involucrada. Si desea volver a utilizar el código, eche un vistazo a la función mixin de Ruby o componga sus objetos complejos de varios objetos "pequeños" que tengan el comportamiento que desea reutilizar.

+0

Muy buena respuesta, excepto por una cosa: está totalmente bien cambiar la firma de los constructores de las subclases. Eso es porque siempre sabes con qué clase estás tratando cuando estás creando una instancia. Por lo tanto, la polimorfia no necesita ser considerada para los constructores. (excepción notable: es posible que desee las mismas interfaces/similares para los constructores cuando está haciendo metaprogramación o está creando algún tipo de fábrica de magia.) – Franz

+0

Tiene razón sobre la firma del constructor: son o.k. cambiar. Eso no significa que sea genial tener un comportamiento completamente divergente del constructor de la base y la subclase. – averell

2

¿Cuál es la razón por la que desea que B herede de A? A menos que tenga otra razón, la forma correcta de diseñar esto sería simplemente tomar el nombre como parámetro para el constructor B y deshacerse de la herencia.

class A 
    attr_accessor :name 

    def initialize params 
    @name = params[:name] 
    @collection << B.new(@name) 
    end 
end 

class B 
    def initialize name 
    @my_name = lookup_something(@name) 
    end 
end 
2

John Nunemaker tiene un bonito article sobre el tema.

Cuestiones relacionadas