2009-06-15 16 views
8

Ruby non sembra avere un impianto per la definizione di un blocco protetto/privato in questo modo:Blocco privato/protetto in Ruby?

protected do 
    def method 
    end 
end 

Questo sarebbe bello rispetto ad

protected 

def method 
end 

public 

dove si potrebbe dimenticare di "pubblico" dopo i metodi protetti

Sembra possibile implementarlo utilizzando metaprogramming. Qualche idea come?

risposta

15

Dato che si desidera raggruppare per funzionalità, è possibile dichiarare tutti i metodi, quindi dichiarare quali sono protetti e privati ​​utilizzando protetto seguito dai simboli dei metodi che si desidera proteggere e lo stesso per privato.

La seguente classe mostra cosa intendo. In questa classe tutti i metodi sono pubblici tranne bar_protected e bar_private che sono dichiarati protetti e privati ​​alla fine.

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

ho deciso di accettare questa come risposta perché è così che viene definito Ruby. Supponevo che metaprogrammare un blocco protetto fosse facile, ma a quanto pare non lo è. Ed è meglio non eseguire la metaprogrammazione finché non è possibile confermare tramite test che funzioni. Comunque, grazie a Chuck per aver provato il problema :) – gsmendoza

+1

Sembra privato e protetto dovrebbe essere un blocco. Mi chiedo perché non lo siano. – mysmallidea

+0

I second cosa ha detto @RyanHeneise: qualcuno è in grado di fornire ulteriori informazioni su questa convenzione? – Noz

9

Io in realtà condivido la soluzione di bodnarbm e non consiglio di fare questo, ma poiché non posso lasciarmi sfuggire una sfida metaprogrammazione, ecco un hack che servirà allo scopo:

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

Grazie! Lo proverò :) – gsmendoza

+0

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

Problemi correlati