2009-06-15 17 views
8

Ruby no parecen tener una facilidad para definir un bloque protegido/privada, así:Bloque privado/protegido en Ruby?

protected do 
    def method 
    end 
end 

Esto sería bueno comparado con

protected 

def method 
end 

public 

donde es posible que se olvide de "público" después de los métodos protegidos

Parece posible implementar esto mediante la metaprogramación. Alguna idea de como?

Respuesta

15

Como quiera agrupar por funcionalidad, puede declarar todos sus métodos, y luego declarar cuáles están protegidos y privados mediante el uso de protected seguido de los símbolos de los métodos que desea proteger, y lo mismo para privado.

La siguiente clase muestra a qué me refiero. En esta clase, todos los métodos son públicos, excepto bar_protected y bar_private, que se declaran protegidos y privados al final.

class Foo 

    def bar_public 
    print "This is public" 
    end 

    def bar_protected 
    print "This is protected" 
    end 

    def bar_private 
    print "This is private" 
    end 

    def call_protected 
    bar_protected 
    end 

    def call_private 
    bar_private 
    end 

    protected :bar_protected 

    private :bar_private 

end 
+0

decidí aceptar este como la respuesta porque así es como se define Ruby. Asumía que metaprogramar un bloque protegido debería ser fácil, pero aparentemente no lo es. Y, es mejor no hacer metaprogramación hasta que pueda confirmar mediante pruebas que funciona. Aún así, gracias a Chuck por probar el problema :) – gsmendoza

+1

Parece que deben ser bloques privados y protegidos. Me pregunto por qué no lo son. – mysmallidea

+0

En segundo lugar, lo que dijo @RyanHeneise: ¿alguien puede brindar más información sobre esta convención? – Noz

9

realidad estoy de acuerdo con la solución de bodnarbm y no recomiendo hacer esto, pero ya que no puedo dejar pasar un desafío metaprogramming, esto es un truco que hará:

class Module 
    def with_protected 
    alias_if_needed = lambda do |first, second| 
     alias_method first, second if instance_methods.include? second 
    end 
    metaclass = class<<self; self end 
    metaclass.module_eval {|m| alias_if_needed[:__with_protected_old__, :method_added]} 
    def self.method_added(method) 
     protected method 
     send :__with_protected_old__ if respond_to? :__with_protected_old__ 
    end 
    yield 
    metaclass.module_eval do |m| 
     remove_method :method_added 
     alias_if_needed[:method_added, :__with_protected_old__] 
    end 
    end 
end 
+0

¡Gracias! Lo probaré :) – gsmendoza

+0

¡¡omg !!! 1 !! 11ONE! – rogi

Cuestiones relacionadas