2012-07-24 8 views
6

In Ruby, ist mein Verständnis, dass self ist der implizite Empfänger für jeden nackten Methodenaufruf. Jedoch:Wenn `self` in Ruby immer der implizierte Empfänger ist, warum funktionieren` self.puts` nicht?

~: irb 
>> puts "foo" 
foo 
=> nil 
>> self.puts "foo" 
NoMethodError: private method `puts' called for main:Object 

Was erklärt dies?

Im Fall ist es keine Hilfe:

>> method(:puts).owner 
=> Kernel 
+1

versuchen Sie 'self.send: puts," foo "'. Mit send können Sie private Methoden umgehen. – DGM

Antwort

8

Private Methoden können nicht einen Empfänger haben

Ich denke, die Antwort ist: Ruby Weg Methode Privatsphäre der Durchsetzung ist, dass es nicht private Methoden mit einem expliziten Empfänger Aufruf nicht gestattet.

Ein Beispiel:

class Baker 
    def bake_cake 
    make_batter 
    self.use_oven # will explode: called with explicit receiver 'self' 
    end 

    private 
    def make_batter 
    puts "making batter!" 
    end 

    def use_oven 
    puts "using oven!" 
    end 

end 

b = Baker.new 
b.bake_cake 

Da es keinen expliziten Empfänger sein kann, man kann sicherlich b.use_oven nicht tun. Und so wird die Privatsphäre der Methode durchgesetzt.

+0

aber puts ist eine öffentliche Methode, method (: puts) .owner.public_methods.grep/puts/returns [: puts]. MRI Ruby 1.93p194 – dfang

+0

Sorry, ich habe die Methode Lookup vergessen. self.class.ancestors => [Objekt, Kernel, BasicObject] – dfang

+0

@dfang - vielleicht wird es von einer Kindklasse als privat eingestuft? –

3

Sie richtig sind, dass self der implizite Empfänger ist, wenn Sie eine nicht explizit angeben. Der Grund dafür, dass Sie nicht tun dürfen, ist, dass Sie keine privaten Methoden mit einem expliziten Empfänger aufrufen dürfen (selbst wenn dieser Empfänger self ist) und wie die Fehlermeldung sagt, puts ist eine private Methode.

1

Sie können nicht auf private Methoden in Ruby mit der self. Syntax oder allgemein mit einem Empfänger (etwas vor der .) zugreifen. Dies ist nur für geschützte Methoden möglich.

4

Da ist die Definition der Privatsphäre in Ruby: Private Methoden können nur mit einem impliziten Empfänger aufgerufen werden.

Eigentlich gibt es eine Ausnahme von dieser Regel: weil foo = barimmer eine lokale Variable erstellt, werden Sie private Setter wie self.foo = bar, anrufen dürfen, weil sonst würden Sie nicht in der Lage sein, sich bei allenzu nennen (ohne mit Reflexion).

+1

+1 zum Anzeigen der Ausnahme. –

+0

Neben der Reflexion können Sie 'foo = (bar)' verwenden, ohne 'self' zu verwenden. –

+1

@AndrewGrimm: Funktioniert nicht, ich habe es gerade versucht. Es macht auch Sinn, dass das nicht funktioniert, weil Klammern für die Ausdruckgruppierung verwendet werden können, so dass es eine vollkommen gültige lokale Variablenzuweisung ist. –

Verwandte Themen