Herencia y Variables de la Instancia

Considere el siguiente ejemplo:

[~/srcLPP/inheritance]$ cat VariableInheritance.rb 
class Point
  def initialize(x,y)
    @x,@y = x, y
  end

  def to_s
    "#@x #@y"
  end
end

class Point3D < Point
  def initialize(x, y, z)
    super(x, y)
    @z = z
  end

  def to_s
    "#@x #@y #@z"
  end
end

if __FILE__ == $0
  q, r, s = Point3D.new(1,1,1), Point3D.new(2,2,2), Point3D.new(3,3,3)
  puts q, r, s

  print "The instance variables of point 'q' are: "
  puts q.instance_variables.join(',')
end
Observe como en la línea 18 accedemos a las referencias @x y @y de la superclase Point. Este código funciona como cabría esperar:

[~/srcLPP/inheritance]$ ruby VariableInheritance.rb 
1 1 1
2 2 2
3 3 3
The instance variables of point 'q' are: @x,@y,@z
[~/srcLPP/inheritance]$

Puesto que las variables de instancia no están relacionadas con la herencia, se deduce que una variable de instancia usada por una subclase no puede ocultar una variable de instancia definida usada en la superclase. Si una subclase usa una variable de instancia con el mismo nombre que una variable utilizada por uno de sus ancestros, sobreescribirá el valor de la variable de su ancestro. Esto puede ser que se haga con intencionalidad, para cambiar la conducta del ancestro o puede que ocurra por accidente. En este último caso seguramente dará lugar a bugs.

  1. Observe que, como en el ejemplo, podemos siempre averiguar cuales son las variables de instancia de un objeto q llamando a q.instance_variables
  2. En general, el mecanismo de herencia debe ser usado para extender clases en Ruby sólo cuando estamos familiarizados y tenemos control de la superclase.
  3. Compruebe que nombres usa la superclase para sus variables de instancia y evítelos
  4. Documente sus variables de instancia en la sección para desarrolladores
  5. Prefije los nombres de sus variables de instancia con el nombre de la clase.

Casiano Rodriguez León 2015-01-07