web-dev-qa-db-fra.com

Quelles sont les différences entre "méthodes privées", "publiques" et "méthodes protégées"?

J'apprends Ruby et je suis confus.

Le livre que j'utilise parle de private, public et protected methods, mais je suis encore un peu confus. Quelles sont les différences entre chacun? 

37
Billjk

Public - peut être appelé de n'importe où

Private - La méthode ne peut pas être appelée en dehors de la portée de la classe. L'objet ne peut que s'envoyer le message

ex: le boulanger a la méthode bake publique mais break_eggs est privé

Protected - Vous pouvez appeler les méthodes protégées d'un objet tant que l'objet par défaut self est une instance de la même classe que l'objet dont vous appelez la méthode.

ex: avec la méthode n protected, c1 peut demander à c2 d'exécuter c2.n, car c1 et c2 sont les deux instances de la même classe

Et pour couronner le tout: 

  • Héritage: les sous-classes héritent des règles d'accès aux méthodes de leur super-classe

si "classe D <C", alors D présentera le même comportement d'accès que les instances de C

référence: http://www.Amazon.com/Ruby-Rails-Techniques-Developers/dp/1932394699

36
Julio Marins

Les méthodes public sont ouvertes à tous. En ce qui concerne private versus protected, je me réfère à " méthodes privées Ruby vs méthodes protégées "

Quelle est la différence entre les méthodes "privées" et "protégées" dans Rubis? En Ruby, la principale différence entre un "privé" et La méthode 'protected' est que une méthode privée ne peut pas être appelée avec un récepteur explicite, alors qu'une méthode protégée peut. Qu'est-ce qu'un 'récepteur explicite', vous demandez? Un destinataire explicite est l'objet qui reçoit un message. Dans l'exemple suivant, nous avons un récepteur ('parent') et une méthode ('get_name'). L'objet 'parent' est recevoir l'instruction pour exécuter la méthode 'get_name'.

32
ScottJShea

Consultez " Programmation Ruby/Syntaxe/Classes " pour un exemple détaillé et une explication.

En termes simples, les différences entre les méthodes private, public et protected sont la visibilité de cette méthode dans le programme, un peu comme en lecture seule, en lecture et en écriture et presque invisible.

Contrairement à certains autres langages, vous ne pouvez pas masquer complètement une méthode privée Ruby, vous pouvez uniquement accéder aux méthodes privées pour votre instance d'objet et non pour une autre instance d'objet d'une classe.

Public, bien sûr, est une accessibilité totale et les méthodes sont généralement définies par défaut sur public, à quelques exceptions près.

Les méthodes protégées sont accessibles à partir d'objets de la même classe, voire d'enfants, ce qui n'est pas le cas d'une méthode privée.

6
lifejuggler

La différence sera sur Visibilité et comment ils sont affectés par Héritage

Visibilité :

|| N'importe où || Le public peut être consulté de l'intérieur et de l'extérieur de la classe.

|| Dans la classe || Privé et Protégé ne sont accessibles que de l'intérieur de la classe. 

La similitude entre Protected et Private:

  • Les deux sont accessibles de l’extérieur de la classe via une méthode publique.

Les différences entre Protected et Private sont: 

  • La méthode privée ne peut pas être appelée avec un récepteur (pas même avec #self).SAUF SI... appelant une méthode PRIVATE SETTER . Si vous essayez de supprimer le récepteur, Ruby créera une variable locale. Le moi est un must dans ce cas.

  • Protégé peut ou peut ne pas utiliser soi-même. 

  • Protected peut accéder à la méthode protégée d'un autre objet qui provient de la même classe, Private ne le peut pas. 

Quand il s'agit de Héritage : 

  • Les méthodes privées ne peuvent être appelées implicitement que sur des sous-classes (simplement le nom de la méthode) mais pas explicitement (avec #self).

  • Protected peut être appelé dans les deux sens (avec ou sans #self || de manière implicite ou explicite). 

Exemple avec le code ci-dessous: 

 class Dog
  attr_accessor :name, :age

  def initialize(n, a)
    self.name = n
    self.age = a
  end

  def accessing_private
    "#{self.name} in human years is #{human_years}. This is secret!"
  end

  def accessing_protected
    "Will this work? " + a_protected_method
  end

  def eat_more_than(other) 
  # accessing other instance's protected method from the same class
    daily_diet < other.daily_diet 
    "#{name} eats more than #{other.name}"
  end

  def boy 
    gender_method("boy") # accessing private setter method
  end

  protected

  def daily_diet 
    age * 2 # the younger, the more they have to eat 
  end

  def a_protected_method
    "Yes, I'm protected!"
  end

  private

  attr_writer :gender

  def gender_method(gender)
    self.gender = gender # private setter method requires self
    "#{name} is a #{gender}"
  end

  def human_years
    age * 8
  end
end

# Create the first object of Dog
blake = Dog.new("Blake", 5)

p blake.accessing_private # "Blake in human years is 16. This is secret!"

p blake.accessing_protected # "Will this work? Yes, I'm protected!"

# Create the second object of Dog
jackson = Dog.new("Jackson", 1)

# Below, protected methods from different objects of the same type/class 
# are proven to share access
p jackson.eat_more_than(blake) # true -> "Jackson eats more than Blake"

# Below, accessing private setter method through a public method.
p blake.boy # Blake is a boy 
5
Maya Novarini

Laissez-moi vous expliquer les méthodes Private et protected dans Ruby que dans la plupart des autres langages de programmation Supposons que vous ayez une classe appelée Foo et une sous-classe SubFoo . Dans des langages tels que Java, SubFoo n'a accès à aucune méthode privée définie par Foo . Comme indiqué dans la solution, Ruby ne fournit aucun moyen de masquer les méthodes d'une classe de ses sous -.__ classes. De cette façon, le privé de Ruby’s fonctionne comme Java’s s protected.

Supposons en outre que vous avez deux instances de la classe Foo, a et b. Dans les langues, __. like Java, a et b peuvent s’appeler private methods. Dans Ruby, vous devez utiliser un protected method pour cela. C'est la principale différence entre les méthodes private et protected dans Ruby.

class Foo
  private
  def pri
    'hey I am private of Foo'
  end

  protected
  def prot
    'Hey I am protected of Foo'
  end
end

Maintenant, sous-classe de Foo

class SubFoo < Foo
  def call_pri_of_foo
    pri
  end

  def call_prot_of_foo
    prot
  end
end

Appelez maintenant les accesseurs dans SubFoo

 > sub_foo = SubFoo.new
 => #<SubFoo:0x00000002b56ad8> 
 > sub_foo.call_pri_of_foo
 => "hey I am private of Foo" 
 > sub_foo.call_prot_of_foo
 => "Hey I am protected of Foo"

Jusqu'ici; il semble n'y avoir aucune différence

next_sub_foo = SubFoo.new
 => #<SubFoo:0x00000002b1a0b0>

def next_sub_foo.access_private(child_of_sub_foo)
  child_of_sub_foo.pri
end

def next_sub_foo.access_protected(child_of_sub_foo)
  child_of_sub_foo.prot
end

Appelez maintenant l'accesseur

> next_sub_foo.access_private(sub_foo)
# => NoMethodError: private method `pri' called for #<SubFoo:0x00000002b56ad8>

mais il peut accéder aux méthodes protégées de ses frères et soeurs

> next_sub_foo.access_protected(sub_foo)
# => "Hey I am protected of Foo"

Vous pouvez également consulter le blog de @tenderlove pour plus de clarté http://tenderlovemaking.com/2012/09/07/protected-methods-and-Ruby-2-0.html

3
illusionist

Je pense que casser un récepteur explicite est ce qui est important si vous avez du mal à saisir le concept.

Un destinataire explicite est un objet qui accepte un message.

 person.get_name

person est le destinataire et la méthode "get_name" donne des instructions à l'objet "person" pour exécuter la méthode "get_name".

class Person
    attr_accessor :first_name, :last_name 

  def initialize(first_name, last_name)
    @first_name = first_name
    @last_name = last_name
    puts "And #{phone_number}" # Private method called when initialized
  end

  private 
  def phone_number
    return "XXX-XXX-XXXX"
  end
end


p p1 = Person.new("mike", "jones")


p p1.phone_number # Not within the context of the object instance.

Lorsqu'une méthode est privée, elle ne peut être utilisée que par d'autres méthodes de l'objet dans la classe à laquelle elle est définie.

1
gkstr1

En étudiant les informations que j'ai tirées de ici , j’ai étendu les explications par des erreurs et, à mon avis, aide à comprendre pourquoi et comment utiliser protégé et non privé.

1) protégé:

La ligne numéro 12 plante parce que le paramètre reçu provient d'une autre classe, le message d'erreur est clair:

v.rb:12:in `==': undefined method `sku' for "Object of another class ==> crash":String (NoMethodError)

2) Privé:

Si retirer self des lignes 8 et 12 et que je change protected pour private, planter, car à la ligne 12, other ne sait pas ce que sku est :

v.rb:12:in `==': private method `sku' called for #<Product:0x00000001574e68 @name="Bread", @quantity=1> (NoMethodError)

Le programme:

class Product
  attr_accessor :name, :quantity

  def initialize(name)
    @name = name
    @quantity = 1

    puts "The SKU is #{self.sku}"
  end

  def == (other)
    self.sku == other.sku
  end

  protected
    def sku
      name.crypt("yo")
    end
end

milk1 = Product.new("Milk")
milk2 = Product.new("Milk")
bread = Product.new("Bread")

puts milk1 == bread

puts milk1 == milk2

puts milk1 == "Object of another class ==> crash"
0
Albert Català