Category: rails


Ruby: metodos de clase privados

September 18th, 2008 — 03:57 pm

Ayer aparecio una duda delante de mi y me asalto, ¿Metodos de clase privados?

La primera idea que me paso por la cabeza y que probe fue:

class Test
 
private
def Test.class_method
p "inside private class method"
end
 
end

Si pruebo este codigo en irb,

madtrick:~/programacion/ruby madtrick$ irb
irb(main):001:0> require "test28"
> true
irb(main):002:0> Test.class_method
"inside private class method"
> nil

Podemos ver que no, que esto no funciona porque me deja llamar al metodo perfectamente y todos sabemos que eso no puede pasar ya que en ruby los metodos privados solo permiten ser invocados con un “self” explicito.Realmente lo que acabo de decir no es del todo cierto, ya que los utilizando el metodo send para enviar el mensaje da igual la visibilidad del metodo que lo reciva.

Lo que no entiendo es porque falla, supongo que sera porque la restriccion de visibilidad que implica private solo afectara a los metodos de instancia de la clase.Si alguien quiere aportar mas luz sobre esto…

Volviendo al tema, probemos con el metodo private_class_method.Este metodo cambia la visibilidad de cualquier metodo a privada.Veamos un ejemplo:

class Test
 
def Test.class_method
p "inside private class method"
end
 
private_class_method :class_method
end

Lo probamos,

madtrick:~/programacion/ruby madtrick$ irb
irb(main):001:0> require "test28"
> true
irb(main):002:0> Test.class_method
NoMethodError: private method `class_method' called for Test:Class
from (irb):2

Esto ya es otra cosa,es lo esperado.Este metodo esta muy bien ya que permite cambiar la visibilidad a que por ejemplo herede nuestra clase.

Pero aun nos queda una manera mas de definidir metodos de clase que sean privados.

Como en ruby todo es un objeto, las señoras clases tambien son objetos (de la clase Class).Por tanto tambien pueden tener metodos de instancia, que a efectos practicos se comportan como los metodos de clase definidos de forma normal y corriente en una clase.

¿Y como añado yo metodos de instancia a una clase?Pues hay varios metodos pero el mas sencillo (o por lo menos eso me parece a mi -se aceptan sugerencias) es el siguiente:

class Test
    class << self
      private
        def class_method
         p "inside private class method"
        end
    end
end

Lo que acabamos de hacer es abrir la metaclase o clase-virtual de la clase para añadir un el metodo class_method con visibilidad privada.Para el que no sepa que son las clases virtuales o metaclases, le recomiendo leer los enlaces que menciono al final del post.

Si ejecutamos esto en irb,

madtrick:~/programacion/ruby madtrick$ irb
irb(main):001:0> require "test28"
> true
irb(main):002:0> Test.class_method
NoMethodError: private method `class_method' called for Test:Class
from (irb):2

Una vez mas, funciona correctamente.

Si quieres saber algo mas sobre las metaclasses o clases-virtuales te recomiendo que le heches un vistazo a:

Seein metaclasses clearly

Why virtual classes?

Comment » | programacion, rails, ruby

     Next Entries »