rails - tutorial ruby italiano




Comprensione dei metodi privati in Ruby (5)

class Example
 private
 def example_test
  puts 'Hello'
 end
end

e = Example.new
e.example_test

Questo ovviamente non funzionerà, perché abbiamo specificato il ricevitore esplicito - istanza di Esempio ( e ), e questo è contro una "regola privata".

Ma non riesco a capire, perché non si può fare in Ruby questo:

class Foo
 def public_m
  self.private_m # <=
 end
 private
 def private_m
  puts 'Hello'
 end
end

Foo.new.public_m

L'oggetto corrente all'interno della definizione del metodo public_m (cioè self ) è l'istanza di Foo. Quindi perché non è permesso? Per risolvere il problema devo cambiare self.private_m su private_m . Ma perché questo differisce, non è il self un'istanza di Foo all'interno di public_m ? E chi è il ricevitore della chiamata private_m parole private_m ? Non è questo self - cosa in realtà ometti perché, Ruby lo farà per te (chiamerà private_m su se stesso)?

Spero di non averlo confuso troppo, sono ancora fresco con Ruby.

EDIT: Grazie per tutte le risposte. Mettendoli tutti insieme sono stato in grado (finalmente) di ingannare l'ovvio (e non così ovvio per qualcuno che non ha mai visto cose come Ruby): il self stesso può essere un ricevitore esplicito e implicito e questo fa la differenza. Quindi ci sono due regole, se si desidera chiamare un metodo privato: self deve essere un ricevitore implicito e quell'auto deve essere un'istanza della classe corrente ( Example in tal caso - e che ha luogo solo se self all'interno della definizione del metodo di istanza, durante l'esecuzione di questo metodo). Perfavore, correggimi se sbaglio.

class Example 

 # self as an explicit receiver (will throw an error)
 def explicit 
  self.some_private_method
 end

 # self as an implicit receiver (will be ok)
 def implicit
  some_private_method
 end

 private

 def some_private_method; end
end

Example.new.implicit

Messaggio per chiunque possa trovare questa domanda durante i percorsi di google: può essere utile: http://weblog.jamisbuck.org/2007/2/23/method-visibility-in-ruby


È strano, ma molte cose sui modificatori di visibilità di Ruby sono strane. Anche se self è il ricevitore implicito, in realtà lo spelling lo rende esplicito agli occhi del runtime di Ruby. Quando dice che i metodi privati ​​non possono essere chiamati con un ricevitore esplicito, questo è ciò che significa, anche il conteggio di self .


Aggiunta di alcuni miglioramenti alla soluzione User Gates. Chiamare un metodo privato al metodo di classe o un metodo di istanza è praticamente possibile. Ecco i frammenti di codice. Ma non raccomandato.

Metodo di classe

class Example
  def public_m
    Example.new.send(:private_m)
  end

  private
  def private_m
    puts 'Hello'
  end
end

e = Example.new.public_m

Metodo di istanza

class Example
  def self.public_m
    Example.new.send(:private_m)
  end

  private
  def private_m
    puts 'Hello'
  end
end

e = Example.public_m

IIRC, i metodi privati ​​consentono solo il ricevente implicito (che è sempre auto, ovviamente).


La definizione di private in Ruby è "può essere chiamata solo senza un destinatario esplicito". Ed è per questo che puoi solo chiamare metodi privati ​​senza un ricevitore esplicito. Non c'è altra spiegazione.

Si noti che in realtà esiste un'eccezione alla regola: a causa dell'ambiguità tra le variabili locali e le chiamate al metodo, verrà sempre risolto il problema di essere un'assegnazione a una variabile locale:

foo = :bar

Quindi, cosa fai se vuoi chiamare uno scrittore chiamato foo= ? Bene, devi aggiungere un ricevitore esplicito, perché senza il ricevitore Ruby semplicemente non saprà che vuoi chiamare il metodo foo= invece di assegnare alla variabile locale foo :

self.foo = :bar

Ma cosa fai se vuoi chiamare uno scrittore private chiamato foo= ? Non puoi scrivere self.foo = perché foo= è private e quindi non può essere chiamato con un ricevitore esplicito. Bene, in realtà per questo caso specifico (e solo in questo caso), puoi effettivamente usare un ricevitore esplicito di self per chiamare uno scrittore private .


Scusa per la mia risposta precedente. Non capisco la tua domanda.

Ho cambiato il tuo codice in questo modo:

class Foo
 def public_m
  private_m # <=
 end

 def Foo.static_m
   puts "static"
 end

 def self.static2_m
   puts "static 2"
 end

 private 
 def private_m
  puts 'Hello'
 end
end

Foo.new.public_m
Foo.static_m
Foo.static2_m

Ecco una chiamata del metodo di istanza:

 def public_m
  private_m # <=
 end

Ecco una chiamata di metodi di classe:

 def Foo.static_m
   puts "static"
 end

 def self.static2_m
   puts "static 2"
 end

Foo.static_m
Foo.static2_m






access-specifier