Ruby: metodos de clase privados
September 18th, 2008 — 03:57 pmAyer 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: