Copia negli appunti

TwitterFacebook

Accesso pubblico, privato e protetto – tutti i programmatori hanno familiarità con questo concetto. Niente di speciale, lavoriamo con loro ogni giorno. Tuttavia, come programmatori Ruby, conosciamo davvero i dettagli?

Puoi verificare te stesso con queste cinque affermazioni. Prova a rispondere: VERO o FALSO.

Istruzioni:

  1. I metodi pubblici non hanno alcun controllo di accesso: possono essere chiamati dall’esterno della definizione della classe dall’istanza di quella classe o dalle sue sottoclassi.
  2. Non è possibile chiamare sia i metodi protetti che quelli privati dall’esterno della classe di definizione.
  3. I metodi protetti sono accessibili dalla sottoclasse e i metodi privati no.
  4. I metodi privati della classe di definizione possono essere richiamati da qualsiasi istanza di quella classe.
  5. L’accesso pubblico è quello predefinito.

Torneremo alle risposte corrette alla fine di questo articolo. Per ora andiamo più in profondità in alcune sfumature di controllo degli accessi pubblici, privati e protetti. Per renderlo più pratico ho preparato un codice di esempio con cui giocare. Raccomando di clonare questo repository per semplificare la continuazione dell’articolo. E ‘ solo un file. Se vuoi pensare prima alla soluzione, tieni a bada l’esecuzione del codice.

Ecco il codice di esempio:

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?

Puoi vedere la classe baseRegionqui insieme a due classi figlio:CountryeCityCity e Country ereditano da Region. L’ereditarietà viene utilizzata per dimostrare i dettagli pubblici, privati e protetti. Alla fine del file, possiamo trovare la parte di inizializzazione e 4 sezioni che discuteremo di seguito. Dai un’occhiata al file per familiarizzare con il codice.

Ok, iniziamo! Nella terza sezione dell’inizializzazione, vengono creati i seguenti oggetti: wroclawsan_franciscoe poland. Questi oggetti saranno utilizzati a scopo dimostrativo nelle prossime sezioni. Suggerisco di trattare tutti questi segmenti separatamente. Puoi commentare la sezione particolare prima di passare a quella successiva. In questo modo, gli errori non bloccheranno il resto dell’output.

I Sezione

Argomento: Accesso pubblico.

Nella prima sezionegreetingil metodo viene richiamato due volte: dagli oggettiwroclawe dagli oggettipoland. Niente di speciale qui. L’accesso del pubblico è semplice. greeting è accessibile per l’oggetto della sua classe (poland) e per l’oggetto della sua classe figlio (wroclaw).

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

Conclusione: l’accesso pubblico è evidente e intuitivo. Non ci sono restrizioni. Inoltre, è il modificatore di accesso predefinito.

II Sezione

Argomento: Accesso ai metodi privati e protetti dall’esterno della classe di definizione.

Ci sono due metodi importanti in quella sezione: protectedname_infoe privatepopulation_info. Il risultato sembra essere di nuovo intuitivo. wroclaw l’oggetto non ha accesso né ai metodi privati né a quelli protetti. In entrambi i casi viene generatoNoMethodError.

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

Conclusione: i metodi privati e protetti non possono essere chiamati dall’esterno della classe. L’accesso è limitato.

III Sezione

Argomento: Accesso ai metodi privati e protetti dall’interno della classe di definizione.

Questa volta abbiamo City::own_greeting che utilizza ereditato metodo protetto all’interno (name_info) e Country::own_greeting che utilizza ereditato metodo privato interno (population_info). Sia i metodi privati che quelli protetti (anche se ereditati) sono accessibili all’interno della classe. Quindi non è il punto che distingue l’accesso privato da quello protetto.

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

Conclusione: i metodi privati e protetti possono essere chiamati dall’interno della classe di definizione. L’accesso è consentito.

IV Sezione

Argomento: differenza effettiva tra metodi privati e protetti.

IV Section-Regole più inaspettate possono iniziare ad apparire qui.Puoi vedere 3 metodi pubblici lì:

  • more_densely_populated?(other_region) – usa privatepopulation_density all’interno.
  • the_same_continent?(other_region) – utilizza protettocontinent all’interno.
  • can_be_crowdy? – utilizza privatoconsider_as_densely_populated? all’interno.

Passiamo attraverso il codice passo dopo passo:

more_densely_populated?(other_region)

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

Hmm, questo è interessante. Il metodo privato Region::population_densitynon è stato chiamato, anche se è implementato all’interno della classe Region. Lo scenario simile è stato lavorato nella sezione III the

the_same_continent?(other_region)

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

Questo funziona. Qualche differenza qui? A destra,the_same_continent? utilizza l’attributo protetto – continent. Ok, continuiamo.

can_be_crowdy?

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

NoMethodError

di nuovo. Hmm,can_be_crowdy? utilizza anche il metodo privatoconsider_as_densely_populated?. Situazione simile stava funzionando bene nella sezione III. Allora, che succede qui?

È tutto sul ricevitore.

Fondamentalmente il ricevitore è l’oggetto il cui metodo è invocato. Andiamo direttamente agli esempi:

  • other_region.population_density ? – Il ricevitore è other_region.
  • other_region.continent – Il ricevitore èother_region.
  • self.consider_as_densely_populated? – Il ricevitore èself.

Ed ecco le cose importanti, ricorda quella regola:

I metodi privati non possono essere chiamati con un ricevitore esplicito.

Presta attenzione alla parola ‘explicit’ qui. Semplificando questa istruzione-non è possibile chiamare il metodo privato scrivendo l’invocazione in questo modo – object.some_method. È necessario utilizzare pure some_method. In quest’ultimo caso Ruby utilizza il ricevitore implicito, che è sempre self. Indipendentemente da questo fatto, non puoi ancora chiamare un metodo privato con self.some_method, perché è ancora un ricevitore esplicito e le regole sono regole:)

Tornando ai nostri metodi:

  • other_region.population_density ? – L’esplicita ricevitore e il metodo privato – NoMethodError
  • other_region.continent – L’esplicita ricevitore è presente e l’attributo è protetta OK
  • self.consider_as_densely_populated? L’esplicita ricevitore e il metodo privato – NoMethodError

Conclusione: Questo è l’attuale distinzione tra privato e protetto. I metodi privati non possono essere chiamati con un ricevitore esplicito e quelli protetti possono. Sulla base della mia esperienza, i metodi protetti sono usati raramente tra le righe di codice Ruby, ma possono essere utili durante il confronto dei parametri, ad esempio, quando vogliamo limitare l’accesso all’attributo ma vogliamo comunque usarlo nel metodo di confronto.

Spero che le regole di controllo degli accessi siano molto più chiare ora. Ti incoraggio a sporcarti le mani con il codice se non l’avessi già fatto. La teoria tende ad essere dimenticata se non è provata.

Alla fine, come ho promesso-risposte alle dichiarazioni:

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

Riepilogo

Ho scritto questo articolo perché per me è stato anche sorprendente come l’accesso pubblico, privato e protetto funzioni effettivamente in Ruby. Le cose più semplici sono le più difficili da capire, o almeno possono essere. Spero davvero che questo articolo è stato utile per voi. O forse, eri a conoscenza delle regole di accesso prima di leggerlo. Condividi i tuoi pensieri nei commenti, sono molto curioso di loro. Puoi dare un’occhiata anche ai documenti. Troverete tutti questi dettagli lì 🙂

join

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.