Copiar al portapapeles

TwitterFacebook

Acceso público, privado y protegido: todos los programadores están familiarizados con ese concepto. Nada especial, trabajamos con ellos a diario. Sin embargo, como programadores de Ruby, ¿realmente conocemos los detalles?

Puede comprobarse a sí mismo con estas cinco declaraciones. Intenta responder: VERDADERO o FALSO.Declaraciones

:

  1. Los métodos públicos no tienen control de acceso, pueden ser llamados desde el exterior de la definición de clase por la instancia de esa clase o sus subclases.
  2. Los métodos protegidos y privados no se pueden llamar desde el exterior de la clase definidora.
  3. Los métodos protegidos son accesibles desde la subclase y los métodos privados no.
  4. Los métodos privados de la clase definidora pueden ser invocados por cualquier instancia de esa clase.
  5. El acceso público es el predeterminado.

Volveremos a las respuestas correctas al final de este artículo. Por ahora, profundicemos en algunos matices del control de acceso público, privado y protegido. Para hacerlo más práctico, preparé un código de ejemplo para jugar. Recomiendo clonar este repositorio para que continuar con el artículo sea más fácil. Es sólo un archivo. Si desea pensar primero en la solución, espere a ejecutar el código.

Aquí está el código de ejemplo:

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?

Usted puede ver la base de la clase Region aquí junto con el niño de dos clases: Country y CityCity y Country heredar de Region. La herencia se utiliza para demostrar los detalles públicos, privados y protegidos. Al final del archivo, podemos encontrar la parte de inicialización y 4 secciones que discutiremos a continuación. Echa un vistazo al archivo para familiarizarte con el código.

Ok, ¡empecemos! En la sección 3ª de la inicialización, los siguientes objetos se crean – wroclawsan_francisco y poland. Estos objetos se utilizarán con fines de demostración en las próximas secciones. Sugiero tratar todos estos segmentos por separado. Puedes comentar la sección en particular antes de pasar a la siguiente. De esa manera, los errores no bloquearán el resto de la salida.

Sección I

Tema: Acceso público.

En la primera sección greeting método es invocado dos veces: por el wroclaw y el poland objetos. Nada especial aquí. El acceso público es sencillo. El greeting es accesible para su clase del objeto (poland) y para su hijo de la clase del objeto (wroclaw).

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

Conclusión: el acceso del Público es evidente e intuitivo. No hay restricciones. Además, es el modificador de acceso predeterminado.

II Sección

Tema: Acceso a los métodos privados y protegidos desde el exterior de la clase definidora.

Hay dos métodos importantes en esa sección: protegido name_info y privada population_info. El resultado parece ser intuitivo de nuevo. wroclaw el objeto no tiene acceso ni a los métodos privados ni a los protegidos. En ambos casos se lanza NoMethodError.

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

Conclusión: Los métodos privados y protegidos no se pueden llamar desde fuera de la clase. El acceso está restringido.

Sección III

Tema: Acceso a métodos privados y protegidos desde el interior de la clase definidora.

Esta vez tenemos City::own_greeting que utiliza heredado método protegido en el interior (name_info) y Country::own_greeting que utiliza heredado método privado interior (population_info). Tanto los métodos privados como los protegidos (incluso si son heredados) son accesibles dentro de la clase. Así que no es el punto que distingue el acceso privado del protegido.

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

Conclusión: Privado y protegido métodos que pueden ser llamados desde el interior de la definición de clase. El acceso está permitido.

Sección IV

Tema: Diferencia real entre métodos privados y protegidos.

Sección IV-Aquí pueden aparecer más reglas inesperadas.Puedes ver 3 métodos públicos allí:

  • more_densely_populated?(other_region) – usa privado population_density dentro.
  • the_same_continent?(other_region) – utiliza protegido continent en el interior.
  • can_be_crowdy? – utiliza privado consider_as_densely_populated? en el interior.

Repasemos el código paso a paso:

more_densely_poblated?(other_region)

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

Hmm, interesante. No se ha llamado al método privado Region::population_density, aunque esté implementado dentro de la clase Region. El escenario similar se ha trabajado en la sección III…

the_same_continent?(other_region)

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

Esto funciona. ¿Hay alguna diferencia? A la derecha, the_same_continent? utiliza el atributo protegido – continent. Bien, continuemos.

can_be_crowdy?

san_francisco.can_be_crowdy?=> private method `consider_as_densely_populated?' called for #<City:0x...> (NoMethodError)
NoMethodError nuevo. Hmm, can_be_crowdy? también utiliza el método privado consider_as_densely_populated?. Una situación similar funciona bien en la sección III. Entonces, ¿qué está pasando aquí?

Todo se trata del receptor.

Básicamente, el receptor es el objeto cuyo método se invoca. Vamos a ir directamente a los ejemplos:

  • other_region.population_density ? – El receptor es other_region.
  • other_region.continent – El receptor es other_region.
  • self.consider_as_densely_populated? – El receptor es self.

Y aquí está lo importante, recuerde esa regla:

Los métodos privados no se pueden llamar con un receptor explícito.

preste atención a la palabra ‘explícito’ aquí. Simplificando esta instrucción – no puede llamar al método privado escribiendo la invocación de esta manera – object.some_method. Debe usar pure some_method. En este último caso, Ruby utiliza el receptor implícito, que siempre es self. Independientemente de ese hecho, aún no puede llamar a un método privado mediante self.some_method, porque sigue siendo un receptor explícito, y las reglas son reglas:)

Volviendo a nuestros métodos:

  • other_region.population_density ? – La explícita receptor está presente y el método es privado – NoMethodError
  • other_region.continent – La explícita receptor está presente y el atributo protegido ACEPTAR
  • self.consider_as_densely_populated? La explícita receptor está presente y el método es privado – NoMethodError

Conclusión: Esta es la distinción entre lo privado y protegido. Los métodos privados no se pueden llamar con un receptor explícito y los protegidos sí. Según mi experiencia, los métodos protegidos rara vez se usan entre las líneas de código Ruby, pero pueden ser útiles al comparar parámetros, por ejemplo, cuando queremos restringir el acceso al atributo pero aún queremos usarlo en el método de comparación.

Espero que las reglas de control de acceso sean mucho más claras ahora. Te animo a que te ensucies las manos con el código si no lo has hecho ya. La teoría tiende a olvidarse si no es comprobada.

Al final, como prometí – respuestas a las declaraciones:

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

Resumen

he escrito este artículo porque para mí también fue sorprendente lo público, privado y de acceso protegido en realidad el trabajo en Rubí. Las cosas más simples son las más difíciles de entender, o al menos pueden serlo. Realmente espero que este artículo te haya sido útil. O tal vez, usted era consciente de las reglas de acceso antes de leerlo. Comparte tus pensamientos en los comentarios, tengo mucha curiosidad por ellos. También puedes echar un vistazo a los documentos. Encontrará todos estos detalles allí 🙂

join

Deja una respuesta

Tu dirección de correo electrónico no será publicada.