class Example
private
def example_test
puts 'Hello'
end
end
e = Example.new
e.example_test
Bien sûr, cela ne fonctionnera pas, car nous avons spécifié l'instance de récepteur explicite de l'exemple (e
), et c'est contre une "règle privée".
Mais je ne peux pas comprendre pourquoi on ne peut pas faire dans Ruby ceci:
class Foo
def public_m
self.private_m # <=
end
private
def private_m
puts 'Hello'
end
end
Foo.new.public_m
L'objet actuel à l'intérieur de public_m
la définition de méthode (c'est-à-dire self
) est l'instance de Foo. Alors pourquoi ce n'est pas permis? Pour résoudre ce problème, je dois changer self.private_m
pour juste private_m
. Mais pourquoi cela diffère, le self
n'est-il pas une instance de Foo dans public_m
? Et qui est le destinataire de la parole nue private_m
appel? N'est-ce pas self
- qu'est-ce que vous omettez réellement parce que, Ruby le fera pour vous (appellera private_m sur vous-même)?
J'espère que je ne l'ai pas trop confondu, je suis encore frais pour Ruby.
EDIT: Merci pour toutes les réponses. En les rassemblant, j'ai (enfin) pu voir l'évidence (et pas si évident pour quelqu'un qui n'a jamais vu des choses comme Ruby): que self
lui-même peut être un récepteur explicite et implicite et qui fait la différence . Il y a donc deux règles, si vous voulez appeler une méthode privée: self
doit être un récepteur implicite, et ce self doit être une instance de la classe actuelle (Example
dans ce cas - et cela prend placer uniquement lorsque self si à l'intérieur de la définition de méthode d'instance, pendant l'exécution de cette méthode). S'il vous plait corrigez moi si je me trompe.
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
Message pour tous ceux qui ont pu trouver cette question pendant les parcours Google: cela peut être utile - http://weblog.jamisbuck.org/2007/2/23/method-visibility-in-Ruby
Voici le court et le long. Ce que signifie privé dans Ruby est une méthode ne peut pas être appelée avec des récepteurs explicites, par exemple some_instance.private_method (value). Donc, même si le récepteur implicite est self, dans votre exemple, vous utilisez explicitement self so les méthodes privées ne sont pas accessibles.
Pensez-y de cette façon, vous attendriez-vous à pouvoir appeler une méthode privée en utilisant une variable que vous avez affectée à une instance d'une classe? Non. Self est une variable et doit donc suivre les mêmes règles. Cependant, lorsque vous appelez simplement la méthode à l'intérieur de l'instance, cela fonctionne comme prévu, car vous ne déclarez pas explicitement le récepteur.
Ruby étant ce que c'est, vous pouvez réellement appeler des méthodes privées en utilisant instance_eval:
class Foo
private
def bar(value)
puts "value = #{value}"
end
end
f = Foo.new
begin
f.bar("This won't work")
rescue Exception=>e
puts "That didn't work: #{e}"
end
f.instance_eval{ bar("But this does") }
J'espère que c'est un peu plus clair.
-- Éditer --
Je suppose que vous saviez que cela fonctionnera:
class Foo
def public_m
private_m # Removed self.
end
private
def private_m
puts 'Hello'
end
end
Foo.new.public_m
definition of private
in Ruby is "can only be called without an explicit receiver". Et c'est pourquoi vous ne pouvez appeler que des méthodes privées sans récepteur explicite. Il n'y a pas d'autre explication.
Notez qu'il existe en fait une exception à la règle: en raison de l'ambiguïté entre les variables locales et les appels de méthode, ce qui suit toujours sera résolu pour être une affectation à une variable locale:
foo = :bar
Alors, que faites-vous si vous voulez appeler un écrivain appelé foo=
? Eh bien, vous avez pour ajouter un récepteur explicite, car sans le récepteur Ruby ne saura tout simplement pas que vous voulez appeler la méthode foo=
au lieu de l'assigner à la variable locale foo
:
self.foo = :bar
Mais que faites-vous si vous voulez appeler un écrivain private
appelé foo=
? Vous ne pouvez pas écrire self.foo =
car foo=
est private
et ne peut donc pas être appelé avec un récepteur explicite. Eh bien, en fait pour ce cas spécifique (et ce cas seul), vous pouvez utilisez en fait un récepteur explicite de self
pour appeler un rédacteur private
.
C'est bizarre, mais beaucoup de choses sur les modificateurs de visibilité de Ruby sont bizarres. Même si self
est le récepteur implicite, l'épeler le rend explicite aux yeux du runtime Ruby. Quand il dit que les méthodes privées ne peuvent pas être appelées avec un récepteur explicite , c'est ce que cela signifie, même self
compte.
IIRC, les méthodes privées permettent seulement récepteur implicite (qui est toujours soi, bien sûr).
Ajout de quelques améliorations à la solution User Gates. L'appel d'une méthode privée à une méthode de classe ou une méthode d'instance est à peu près possible. Voici les extraits de code. Mais non recommandé.
Méthode de 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
Méthode d'instance
class Example
def self.public_m
Example.new.send(:private_m)
end
private
def private_m
puts 'Hello'
end
end
e = Example.public_m
Désolé pour ma réponse précédente. Je ne comprends tout simplement pas votre question.
J'ai changé votre code comme ceci:
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
Voici un appel de méthode d'instance:
def public_m
private_m # <=
end
Voici un appel de méthodes de classe:
def Foo.static_m
puts "static"
end
def self.static2_m
puts "static 2"
end
Foo.static_m
Foo.static2_m
Ne répond pas exactement à la question, mais vous pouvez appeler des méthodes privées de cette façon
class Example
private
def example_test
puts 'Hello'
end
end
e = Example.new
e.send(:example_test)