viernes, 5 de diciembre de 2008

el NilClass

Vean el siguiente ejemplo



# un array asociativo
array = { 1 => "Robert", 2 => "Ruby" }

# imprimir las longitudes de las cadenas del array
(1..3).each do |i|
# CUIDADO al tratar de procesar el string numero 3, se generara un error
# "undefined method 'length' for nil:NilClass (NoMethodError)"
print "longitud de la cadena #{i}: #{array[i].length}\n"
end



el elemento 3 del array asociativo, era un nil, por lo tanto devolvio ese error, pero, trato de invocar el metodo al objeto nil, que es de tipo NilClass, eso significa que se puede definir el metodo en el objeto



# un array asociativo
array = { 1 => "Robert", 2 => "Ruby" }

# antes, puedo definir el metodo length del nil
def nil.length
0
end

# imprimir las longitudes de las cadenas del array
(1..3).each do |i|
# Esta vez no genera ningun error
print "longitud de la cadena #{i}: #{array[i].length}\n"
end


Tambien es valido definir el metodo en el NilClass, por lo que conozco es lo mismo (NilClass es una clase cuya unica instancia es nil)


# un array asociativo
array = { 1 => "Robert", 2 => "Ruby" }

# antes, puedo definir el metodo length en la clase NilClass
class NilClass
def length
0
end
end

# imprimir las longitudes de las cadenas del array
(1..3).each do |i|
# Esta vez no genera ningun error
print "longitud de la cadena #{i}: #{array[i].length}\n"
end




En definitiva, para explicar lo ocurrido, nil es el objeto referenciado por las variables que no referencia a nada, es algo parecido al hecho de conceptualizar una entidad que creo la parte del universo que no fue creada por nadie, o la definicion del "eter" gas que conduce las ondas de luz que existe en todo el espacio exterior , donde se suponia que hay "vacio"
A diferencia de lenguajes como java , o .net, los cuales admiten variables que no hagan referencia a *nada*, dando lugar a "NullPointerExceptions", en ruby esto no tiene sentido, por lo tanto no pueden existir variables que apunten a la nada, si existen variables que apuntan al objeto nil, que representa a la nada, lo cual nos lleva a que tanto los lenguajes mencionados anteriormente se rigen por el mismo principio: la nada en un contexto tan abstracto, tiene el mismo nivel de tangibilidad que cualquier algo (como clases, metodos y otras cosas), java define a esa nada como un "null", y ruby como un "nil".
La diferencia que si existe, es que en java esa representacion de nada, es "especial", es algo mas, una cosa aparte; en cambio, en ruby, la representacion de la nada, es nil, que tambien es un objeto ya que en ruby todo es un objeto, por que lo "especial", se admite en la menor medida posible, ya que añade gran complejidad a esto.
Al ser la representacion de nada un objeto como los demas, admite todo lo que los objetos admite: metodos, mas instancias, estado, etc..., si esto tiene sentido o no definira el programador, si quiere usar estas funcionalidades o no, se puede decir tanto que no tiene sentido que la nada tenga "funcionalidades" como tambien se puede decir que no es correcto que la nada no pueda ser tratada como un concepto al igual que los demas, como las clases, metodos y variables
Espero que les haya sido de utilidad, cerramos con otra exhibicion de nil, menos charla y mas accion:


# ESTO NO SE PUEDE HACER, POR RAZONES ¿OBVIAS?
# atencion: todas las lineas de codigo posteriores dan algun tipo de error

# duplicamos el nil original, ya que es un objeto
# esto no anda, no se puede duplicar el concepto de la nada
# para crear otro concepto, el concepto de nada
# es unico (el patron singleton)
otronil = nil.dup

# instanciamos otro nil usando la NilClass
# no se puede fabricar distintos conceptos de nada
# eso conlleva a la nada (valga la redundancia)
otronilmas = NilClass.new


Ahora algo que funcione



# se le pueden definir los metodos que sean al NilClass
# y tambien variables locales
class NilClass
def initialize
super
@vacio = 4
end

def vacio= (a)
@vacio = a
end
def vacio
@vacio
end
end

nil.vacio = 4
print nil.vacio

No hay comentarios: