2010-01-31 7 views
5

Ich muss einige Instanzmethoden privat nach Registrierung dieses Objekts in einem anderen Objekt machen.Machen Instanzmethoden privat in der Laufzeit

Ich möchte das Objekt nicht einfrieren, weil es editierbar bleiben muss, nur mit weniger Funktionalität. Und ich möchte die Methoden nicht unkenntlich machen, da sie intern verwendet werden.

Was ich brauche, ist so etwas wie:

class MyClass 

    def my_method 
    puts "Hello" 
    end 

end 

a = MyClass.new 
b = MyClass.new 

a.my_method       #=> "Hello" 
a.private_instance_method(:my_method) 
a.my_method       #=> NoMethodError 
b.my_method       #=> "Hello" 

Irgendwelche Ideen?

Antwort

4

Was öffentlich ist und was privat ist, ist pro Klasse. Aber jedes Objekt kann seine eigene Klasse haben:

class Foo 

    private 

    def private_except_to_bar 
    puts "foo" 
    end 

end 

class Bar 

    def initialize(foo) 
    @foo = foo.dup 
    class << @foo 
     public :private_except_to_bar 
    end 
    @foo.private_except_to_bar 
    end 

end 

foo = Foo.new 
Bar.new(foo) # => "foo" 

foo.private_except_to_bar 
# => private method `private_except_to_bar' called for #<Foo:0xb7b7e550> (NoMethodError) 

Aber yuck. Betrachten Sie diese Alternativen:

  • Machen Sie die Methode nur öffentlich.
  • Erkunden Sie alternative Designs.
+0

Dies beantwortet meine Zweifel: "Was ist öffentlich und was privat ist pro Klasse.". Ich denke, ich muss andere Alternativen erkunden. –

8

Sie Methode aufrufen können private auf dem Methodennamen jederzeit machen es privat:

>> class A 
>> def m 
>> puts 'hello' 
>> end 
>> end 
=> nil 
>> a = A.new 
=> #<A:0x527e90> 
>> a.m 
hello 
=> nil 
>> class A 
>> private :m 
>> end 
=> A 
>> a.m 
NoMethodError: private method `m' called for #<A:0x527e90> 
    from (irb):227 
    from /usr/local/bin/irb19:12:in `<main>' 

oder von außerhalb der Klasse:

A.send :private, :m 
+0

Das macht die Methode für alle Objekte dieser Klasse und nicht nur für eine private. –

5
class A 
    def test 
    puts "test" 
    end 
    def test2 
    test 
    end 
end 

a = A.new 

class << a 
    private :test 
end 

a.test2 # works 
a.test # error: private method