Antes de leer este artículo , pensé que el control de acceso en Ruby funcionaba así:
public
- Se puede acceder por cualquier objeto (por ejemploObj.new.public_method
)protected
- solo se puede acceder desde el propio objeto, así como desde cualquier subclaseprivate
- igual que protegido, pero el método no existe en subclases
Sin embargo, parece ser que protected
y private
actúan de la misma, excepto por el hecho de que no se puede llamar a private
los métodos con un receptor explícita (es decir, self.protected_method
las obras, pero self.private_method
no lo hace).
¿Cuál es el punto de esto? ¿Cuándo hay un escenario en el que no desea que se llame a su método con un receptor explícito?
ruby
language-design
access-specifier
Kyle Slattery
fuente
fuente
Object
se permitiera a todas las instancias llamar a los métodos privados de cualquier otra instancia deObject
, sería posible decir cosas como5.puts("hello world")
.Respuestas:
protected
cualquier instancia de la clase definitoria o sus subclases puede llamar a los métodos.private
los métodos solo se pueden invocar desde el objeto que realiza la llamada. No puede acceder a los métodos privados de otra instancia directamente.Aquí hay un ejemplo práctico rápido:
some_method
No puede estarprivate
aquí. Debe serprotected
porque lo necesita para admitir receptores explícitos. Sus métodos de ayuda interna típicos generalmente pueden serprivate
ya que nunca necesitan llamarse así.Es importante tener en cuenta que esto es diferente de la forma en que funciona Java o C ++.
private
en Ruby es similar aprotected
en Java / C ++ en que las subclases tienen acceso al método. En Ruby, no hay forma de restringir el acceso a un método desde sus subclases como puede hacerloprivate
en Java.La visibilidad en Ruby es en gran medida una "recomendación" de todos modos ya que siempre puedes obtener acceso a un método usando
send
:fuente
private
vsprotected
tener que ver si una subclase podría heredar un método, pero en realidad se trata de dónde se puede llamar al método. ¡Gracias!send
?La diferencia
self
. Ni siquiera tú puedes llamarself.some_private_method
; debes llamarprivate_method
conself
implícito.self
receptor puede ser explícito,self.some_private_method
está permitido. (Cualquier otro receptor explícito aún no está permitido, incluso si el valor de tiempo de ejecución es el mismo queself
).En Ruby, estas distinciones son solo consejos de un programador a otro. Los métodos no públicos son una forma de decir "Me reservo el derecho de cambiar esto; no dependa de ello". Pero aún obtienes las tijeras afiladas
send
y puedes llamar a cualquier método que desees.Un breve tutorial
Entonces puedes correr
ruby dwarf.rb
y hacer esto:fuente
age=
, puede (y tiene que) llamarloself
para separarlo de las variables locales.gimli.greet
,gimli
no es la persona que llama, sino el receptor. La persona que llama es el "entorno de ejecución de nivel superior", que en realidad es una instancia ad-hoc deObject
. Prueba esto:ruby -e 'p self; p self.class'
Métodos privados en Ruby:
Si un método es privado en Ruby, entonces no puede ser invocado por un receptor explícito (objeto). Solo se puede llamar implícitamente. Se puede llamar implícitamente por la clase en la que se ha descrito, así como por las subclases de esta clase.
Los siguientes ejemplos lo ilustrarán mejor:
1) Una clase Animal con método privado class_name
En este caso:
2) Una subclase de Animal llamada Anfibio:
En este caso:
Como puede ver, los métodos privados solo se pueden invocar implícitamente. No pueden ser llamados por receptores explícitos. Por la misma razón, los métodos privados no se pueden invocar fuera de la jerarquía de la clase definitoria.
Métodos protegidos en Ruby:
Si un método está protegido en Ruby, la clase definitoria y sus subclases pueden invocarlo implícitamente. Además, también pueden ser llamados por un receptor explícito siempre que el receptor sea propio o de la misma clase que el propio:
1) Una clase Animal con método protegido protect_me
En este caso:
2) Una clase de mamífero que se hereda de la clase animal.
En este caso
3) Una clase de anfibios heredada de la clase Animal (igual que la clase mamífero)
En este caso
4) Una clase llamada Árbol
En este caso:
fuente
Considere un método privado en Java. Se puede llamar desde la misma clase, por supuesto, pero también se puede llamar desde otra instancia de esa misma clase:
Entonces, si la persona que llama es una instancia diferente de mi misma clase, mi método privado es realmente accesible desde el "exterior", por así decirlo. En realidad, esto hace que no parezca tan privado.
En Ruby, por otro lado, un método privado realmente está destinado a ser privado solo para la instancia actual. Esto es lo que proporciona la eliminación de la opción de un receptor explícito.
Por otro lado, debo señalar que es bastante común en la comunidad de Ruby no utilizar estos controles de visibilidad, dado que Ruby te ofrece formas de sortearlos de todos modos. A diferencia del mundo de Java, la tendencia es hacer que todo sea accesible y confiar en que otros desarrolladores no arruinen las cosas.
fuente
Parte de la razón por la cual las subclases pueden acceder a métodos privados en Ruby es que la herencia de Ruby con clases es una capa fina de azúcar sobre el Módulo incluye: en Ruby, una clase, de hecho, es un tipo de módulo que proporciona herencia, etc.
http://ruby-doc.org/core-2.0.0/Class.html
Lo que esto significa es que, básicamente, una subclase "incluye" la clase principal de manera que las funciones de la clase principal, incluidas las funciones privadas , también se definen en la subclase.
En otros lenguajes de programación, llamar a un método implica hacer burbujear el nombre del método en una jerarquía de clase primaria y encontrar la primera clase primaria que responde al método. Por el contrario, en Ruby, mientras la jerarquía de la clase principal todavía está allí, los métodos de la clase principal se incluyen directamente en la lista de métodos de la subclase que ha definido.
fuente
Comparación de los controles de acceso de Java con Ruby: si el método se declara privado en Java, solo se puede acceder a él por otros métodos dentro de la misma clase. Si un método se declara protegido, otras clases que existen dentro del mismo paquete pueden acceder a él, así como las subclases de la clase en un paquete diferente. Cuando un método es público, es visible para todos. En Java, el concepto de visibilidad del control de acceso depende de dónde se encuentran estas clases en la jerarquía de herencia / paquete.
Mientras que en Ruby, la jerarquía de herencia o el paquete / módulo no encajan. Se trata de qué objeto es el receptor de un método.
Para un método privado en Ruby, nunca se puede llamar con un receptor explícito. Podemos (solo) llamar al método privado con un receptor implícito.
Esto también significa que podemos llamar a un método privado desde una clase en la que se declara, así como a todas las subclases de esta clase.
Nunca puede llamar al método privado desde fuera de la jerarquía de clases donde se definió.
El método protegido se puede llamar con un receptor implícito, como privado. Además, el método protegido también puede ser llamado por un receptor explícito (solo) si el receptor es "propio" o "un objeto de la misma clase".
Resumen
Público: los métodos públicos tienen máxima visibilidad
Protegido: el método protegido se puede invocar con un receptor implícito, como privado. Además, el método protegido también puede ser llamado por un receptor explícito (solo) si el receptor es "propio" o "un objeto de la misma clase".
Privado: para un método privado en Ruby, nunca se puede llamar con un receptor explícito. Podemos (solo) llamar al método privado con un receptor implícito. Esto también significa que podemos llamar a un método privado desde una clase en la que se declara, así como a todas las subclases de esta clase.
fuente
fuente