Public, protected, private

On a vu comment créer une classe, avec ses méthodes et ses variables d’instance. Le problème de ces méthodes, c’est qu’elles sont publiques par défaut. Donc, en dehors de la classe, on peut appeler ces méthodes et voir ce qu’elles font. On va changer ça.

Protected

Les méthodes protégées ne sont accessibles qu’aux instances de classe et aux instances des classes “enfants”.

class Frigo
  def initialize(nom)
    @marque = nom
  end
  protected
  def quelle_marque
    puts "J'ai un frigo " + @marque + "."
  end
end
mon_frigo = Frigo.new("Brandt")
mon_frigo.quelle_marque → Je reçois une erreur

J’ai ma classe Frigo. Je crée un objet “mon_frigo” où je passe le nom de la marque de mon frigo Brandt (ce qui est totalement faux, car je veux cacher mon identité). Ensuite, je veux savoir de quelle marque est mon frigo parce que je l’ai oubliée. J’appelle la méthode “quelle_marque” mais je reçois une erreur parce qu’elle est protégée (tout ce qui suit “protected” est protégé). Damnation! Mon équilibre nutritionnel est compromis.

J’ai eu du mal à comprendre pourquoi je ne pouvais y accéder, parce que si on relit la définition : “les méthodes protégées ne sont accessibles qu’aux instances de classe”. Tiens, ça ne marche pas alors que “mon_frigo” est bien une instance de Frigo. Donc je vous offre un exemple un peu compliqué pour comprendre le principe du “protected” :

class Equipe
  def initialize(nom)
    @nom = nom
  end
  def argent(club)
    if club.salaire > salaire
      puts "Tu gagnes plus que moi! Je gagne que " + salaire.to_s + "!"
    else
      puts "Petit joueur!!! Je gagne " + salaire.to_s + "!"
    end
  end
  def salaire=(montant)
    @salaire = montant
  end
  protected
  def salaire
    @salaire
  end
end
girondins = Equipe.new("Girondins")
barca = Equipe.new("FC Barcelone")
girondins.salaire = 42
barca.salaire = 948
girondins.argent(barca)
→ Tu gagnes plus que moi! Je gagne que 42!

Une classe Equipe avec un attribut lisible/éditable “salaire”. Puis j’ai ma méthode “argent” qui compare l’argent de 2 clubs. Je crée donc mes 2 équipes, girondins et barca, j’attribue un salaire à chacun d’eux. Enfin, j’appelle la méthode argent pour une instance de la classe Equipe, et avec en paramètre aussi une instance de la classe Equipe. Et ça marche.

En fait, ici, c’est l’attribut salaire qui est protégé (et non pas la méthode argent). Donc, dans cette méthode, lorsque j’écris “club.salaire”, j’appelle un attribut protégé. Mais celui qui l’appelle n’est autre que “girondins”, une instance de la classe Equipe. Donc il a le droit de réponse de lire l’attribut “salaire” du barca.

Si je fais ça en dehors de la classe :

puts girondins.salaire

Je rencontre une erreur.

Private

Une méthode privée n’est accessibles qu’à l’instance actuelle de la classe (contrairement aux méthodes protégées qui sont accessibles aux instances de la même classe et aux instances des classes enfants).

class Equipe
  def initialize(club)
  end
  private
  def soudoiement(individu)
    # Ici je mettrais des actions qui
    # menaceraient les arbitres de L1
    puts "PRENDS GARDE " + individu + "!"
  end
  public
  def arbitre(nom)
    puts "Toi, " + nom + " tu vas faire gagner mon équipe ou sinon..."
    soudoiement(nom)
  end
end
chelsea = Equipe.new("Chel$ea")
chelsea.arbitre("Colina") → PRENDS GARDE Colina!
chelsea.soudoiement("Sartz") # Je reçois une erreur

Ma méthode soudoiement (qui ici ne fait qu’afficher une phrase alors qu’en réalité elle fait beaucoup plus, mais je ne peux rien dire de plus, je suis probablement sous écoute) est appelée par une autre méthode, arbitre, qui elle est publique.
Par contre, si j’appelle la méthode en dehors de la classe (avec l’arbitre Sartz), ça ne marche pas.

A vrai dire, je vois bien ce que font ces 3 niveaux (public, protected, private) mais j’ai du mal à bien le définir. J’espère que les exemples sont plus explicites que moi.

Demain, on parle des variables, méthodes et constantes de classe (et non plus d’instance de classe).