Copier dans le presse-papiers

TwitterFacebook

Accès public, privé et protégé – tous les programmeurs connaissent ce concept. Rien de spécial, nous travaillons avec eux au quotidien. Cependant, en tant que programmeurs Ruby, connaissons-nous vraiment les détails?

Vous pouvez vérifier vous-même avec ces cinq déclarations. Essayez de répondre: VRAI ou FAUX.Instructions

:

  1. Les méthodes publiques n’ont pas de contrôle d’accès – elles peuvent être appelées de l’extérieur de la définition de classe par l’instance de cette classe ou ses sous-classes.
  2. Les méthodes protégées et privées ne peuvent pas être appelées de l’extérieur de la classe de définition.
  3. Les méthodes protégées sont accessibles depuis la sous-classe et les méthodes privées ne le sont pas.
  4. Les méthodes privées de la classe de définition peuvent être invoquées par n’importe quelle instance de cette classe.
  5. L’accès public est celui par défaut.

Nous reviendrons aux bonnes réponses à la fin de cet article. Pour l’instant, approfondissons quelques nuances de contrôle d’accès public, privé et protégé. Pour le rendre plus pratique, j’ai préparé un exemple de code avec lequel jouer. Je recommande de cloner ce dépôt pour faciliter la poursuite de l’article. C’est juste un dossier. Si vous souhaitez d’abord penser à la solution, arrêtez d’exécuter le code.

Voici l’exemple de code:

class Region attr_accessor :name def initialize(name, population, area_size, continent) self.name = name self.population = population self.area_size = area_size self.continent = continent end def greeting puts name_info + population_info end def more_densely_populated?(other_region) result = population_density > other_region.population_density ? 'more' : 'less' puts "#{name} is #{result} densely populated than #{other_region.name}." end def the_same_continent?(other_region) if continent.eql?(other_region.continent) puts "#{name} and #{other_region.name} lie in the same continent." else puts "#{name} and #{other_region.name} lie in the different continents." end end def can_be_crowdy? if self.consider_as_densely_populated? puts "#{name} can be crowdy." else "There is enough space in the #{name}." end end protected attr_accessor :continent def name_info "Hello, I'm #{name}!" end private attr_accessor :population, :area_size def population_info " #{population} people live here." end def population_density population / area_size end def consider_as_densely_populated? population_density > self.class::HIGH_POPULATION_DENSITY endendclass Country < Region HIGH_POPULATION_DENSITY = 300 def own_greeting puts "The country name: #{name}." + population_info endendclass City < Region HIGH_POPULATION_DENSITY = 3000 def own_greeting puts name_info + " The population: #{population} people." endend# initializationwroclaw = City.new('Wrocław', 638_000, 293, 'Europe')san_francisco = City.new('San Francisco', 884_000, 121, 'Northern America')poland = Country.new('Poland', 38_000_000, 312_000, 'Europe')# I sectionwroclaw.greetingpoland.greeting# II sectionwroclaw.name_infowroclaw.population_info# III sectionwroclaw.own_greetingpoland.own_greeting# IV sectionwroclaw.more_densely_populated?(san_francisco)wroclaw.the_same_continent?(san_francisco)san_francisco.can_be_crowdy?

Vous pouvez voir la classe de base Region ici avec deux classes enfants: Country et CityCity et Country héritent de Region. L’héritage est utilisé pour démontrer les détails publics, privés et protégés. À la fin du fichier, nous pouvons trouver une partie d’initialisation et 4 sections dont nous discuterons ci-dessous. Jetez un coup d’œil au fichier pour vous familiariser avec le code.

Ok, commençons! Dans la 3ème section de l’initialisation, les objets suivants sont créés – wroclawsan_francisco et poland. Ces objets seront utilisés à des fins de démonstration dans les prochaines sections. Je suggère de traiter tous ces segments séparément. Vous pouvez commenter la section particulière avant de passer à la suivante. De cette façon, les erreurs ne bloqueront pas le reste de la sortie.

I Section

Sujet: Accès public.

Dans la première section, la méthode greeting est invoquée deux fois: par les objets wroclaw et par les objets poland. Rien de spécial ici. L’accès du public est simple. Le greeting est accessible pour l’objet de sa classe (poland) et pour l’objet de sa classe enfant (wroclaw).

Hello, I'm Wrocław! 638000 people live here.Hello, I'm Poland! 38000000 people live here.

Conclusion: L’accès public est évident et intuitif. Il n’y a aucune restriction. En outre, c’est le modificateur d’accès par défaut.

Section II

Sujet : Accès aux méthodes privées et protégées depuis l’extérieur de la classe de définition.

Il existe deux méthodes importantes dans cette section : protected name_info et privatepopulation_info. Le résultat semble à nouveau intuitif. wroclaw l’objet n’a accès ni aux méthodes privées ni aux méthodes protégées. Dans les deux cas, NoMethodError est lancé.

protected method `name_info' called for #<City:0x...> (NoMethodError)private method `population_info' called for #<City:0x...> (NoMethodError)

Conclusion: Les méthodes privées et protégées ne peuvent pas être appelées de l’extérieur de la classe. L’accès est restreint.

Section III

Sujet : Accès aux méthodes privées et protégées depuis l’intérieur de la classe de définition.

Cette fois, nous avons City::own_greeting qui utilise une méthode protégée héritée à l’intérieur (name_info) et Country::own_greeting qui utilise une méthode privée héritée à l’intérieur (population_info). Les méthodes privées et protégées (même si elles sont héritées) sont accessibles à l’intérieur de la classe. Ce n’est donc pas le point qui distingue l’accès privé de l’accès protégé.

Hello, I'm Wrocław! The population: 638000 people.The country name: Poland. 38000000 people live here.

Conclusion: Les méthodes privées et protégées peuvent être appelées de l’intérieur de la classe de définition. L’accès est autorisé.

Section IV

Sujet: Différence réelle entre les méthodes privées et protégées.Section IV – Des règles plus inattendues peuvent commencer à apparaître ici.Vous pouvez y voir 3 méthodes publiques:

  • more_densely_populated?(other_region) – il utilise private population_density à l’intérieur.
  • the_same_continent?(other_region) – il utilise protégé continent à l’intérieur.
  • can_be_crowdy? – il utilise un consider_as_densely_populated? privé à l’intérieur.

Passons en revue le code étape par étape :

more_densely_populated?(other_region)

wroclaw.more_densely_populated?(san_francisco)=> private method `population_density' called for #<City:0x...> (NoMethodError)

Hmm, c’est intéressant. La méthode privée Region::population_density n’a pas été appelée, même si elle est implémentée dans la classe Region. Le scénario similaire a été travaillé dans la section IIIthe

the_same_continent ?(other_region)

wroclaw.the_same_continent?(san_francisco)=> Wrocław and San Francisco lie in the different continents.

Celui-ci fonctionne. Une différence ici? À droite, the_same_continent? utilise l’attribut protégé – continent. Ok, continuons.

can_be_crowdy?

san_francisco.can_be_crowdy?=> private method `consider_as_densely_populated?' called for #<City:0x...> (NoMethodError)

NoMethodError encore une fois. Hmm, can_be_crowdy? utilise également la méthode privée consider_as_densely_populated?. Une situation similaire fonctionnait bien dans la section III. Alors que se passe-t-il ici?

Tout tourne autour du récepteur.

Fondamentalement, le récepteur est l’objet dont la méthode est invoquée. Passons directement aux exemples:

  • other_region.population_density ? – Le récepteur est other_region.
  • other_region.continent – Le récepteur est other_region.
  • self.consider_as_densely_populated? – Le récepteur est self.

Et voici les choses importantes, rappelez-vous cette règle:

Les méthodes privées ne peuvent pas être appelées avec un récepteur explicite.

Faites attention au mot ‘explicite’ ici. Simplifier cette instruction – vous ne pouvez pas appeler de méthode privée en écrivant l’appel comme ceci – object.some_method. Vous devez utiliser pure some_method. Dans ce dernier cas, Ruby utilise le récepteur implicite, qui est toujours self. Indépendamment de ce fait, vous ne pouvez toujours pas appeler une méthode privée par self.some_method, car c’est toujours un récepteur explicite, et les règles sont des règles 🙂

Revenir à nos méthodes:

  • other_region.population_density ? – Le récepteur explicite est présent et la méthode est privée – NoMethodError
  • other_region.continent – Le récepteur explicite est présent et l’attribut est protégé – OK
  • self.consider_as_densely_populated? – Le récepteur explicite est présent et la méthode est privée – NoMethodError

Conclusion: C’est la distinction réelle entre privé et protégé. Les méthodes privées ne peuvent pas être appelées avec un récepteur explicite et les méthodes protégées le peuvent. D’après mon expérience, les méthodes protégées sont rarement utilisées parmi les lignes de code Ruby, mais elles peuvent être utiles lors de la comparaison de paramètres, par exemple lorsque nous voulons restreindre l’accès à l’attribut mais que nous voulons toujours l’utiliser dans la méthode de comparaison.

J’espère que les règles de contrôle d’accès sont beaucoup plus claires maintenant. Je vous encourage à vous salir les mains avec le code si vous ne l’aviez pas déjà fait. La théorie a tendance à être oubliée si elle n’est pas prouvée.

À la fin, comme je l’ai promis – réponses aux déclarations:

  1. TRUE
  2. TRUE
  3. FALSE
  4. FALSE
  5. TRUE

Résumé

J’ai écrit cet article parce que pour moi, il était également surprenant de voir comment les accès publics, privés et protégés fonctionnent réellement dans Ruby. Les choses les plus simples sont les plus difficiles à comprendre, ou du moins elles peuvent l’être. J’espère vraiment que cet article vous a été utile. Ou peut-être que vous connaissiez les règles d’accès avant de le lire. Partagez vos pensées dans les commentaires, je suis très curieux d’eux. Vous pouvez également consulter les documents. Vous y trouverez tous ces détails 🙂

rejoindre

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.