Puede que le resulte útil leer definición de public, private and protected. de rubí (Pasar a la control de acceso)
privada de Ruby es análoga a la de Java protegido. No hay ningún equivalente Ruby de privado de Java. EDITAR: Esta solución ahora proporciona un método para simular el ideal de privacidad de Java en objetos Ruby.
Privado se define como métodos/variables que pueden llamarse solo implícitamente. Esta es la razón por la cual los enunciados 2 y 3 fallan. En otras palabras, los límites de los métodos/variables al contexto de una clase o subclase en la que están definidos. La herencia pasa los métodos privados a las subclases y, por lo tanto, se puede acceder con un yo implícito. (Explicando por qué funciona la declaración 6)
Creo que está buscando algo más cerca de lo protegido. Que se comporta de manera similar a los accesadores de Java a los que no se les da visibilidad (p. Ej .: pública, privada, protegida) Al cambiar el privado en Spy para proteger los 6 de su trabajo de extractos. Los métodos protegidos pueden invocarse mediante cualquier instancia de la clase definitoria o sus subclases. Llamar explícita o implícitamente a sí mismo son afirmaciones válidas para métodos protegidos siempre que la persona que llama sea la clase del objeto que responde a la llamada o herede de ella.
class Person
private
attr_reader :weight
end
class Spy < Person
protected
attr_accessor :code
public
def test
code #(1) OK: you can call a private method in self
Spy.new.code #(2) OK: Calling protected method on another instance from same class family or a descendant.
self.code #(3) OK: Calling protected method on with explicit self is allowed with protected
code="xyz" #(4) Ok, it runs, but it actually creates a local variable!!!
self.code="z" #(5) OK! This is the only case where explicit 'self' is ok
weight #(6) OK! You can call a private method defined in a base class
end
end
s = Spy.new
s.test # succeeds
s.code #(7) Error: Calling protected method outside of the class or its descendants.
En cuanto a la declaración 4. Tiene razón al suponer que esto es para evitar ambigüedades. Es más una salvaguarda al daño potencial de la naturaleza dinámica de ruby. Asegura que no puede anular los usuarios abriendo nuevamente la clase más tarde. Una situación que puede surgir, por ejemplo, al evaluar un código contaminado.
Solo puedo especular sobre las decisiones de diseño que llevaron a estos comportamientos. Para la mayoría, creo que se reduce a la naturaleza dinámica del lenguaje.
P.S. Si realmente quieres darle a las cosas la definición java de private. Solo disponible para la clase en la que está definido, ni siquiera subclases. Puede agregar un método self.herited a sus clases para eliminar las referencias a los métodos a los que desea limitar el acceso.
hacer el peso atribuyen inaccesible desde subclases:
class Person
private
attr_reader :weight
def initialize
@weight = 5
end
def self.inherited(subclass)
subclass.send :undef_method, :weight
end
end
class Spy < Person
private
attr_accessor :code
public
def test
weight
end
end
Person.new.send(:weight) # => 5
Spy.new.send(:weight) #=> Unhelpful undefined method error
Se puede tener más sentido para reemplazar la llamada undef_method a algo como esto:
def self.inherited(subclass)
subclass.class_eval %{
def weight
raise "Private method called from subclass. Access Denied"
end
}
end
que proporciona un error mucho más servicial y el misma funcionalidad.
El envío es necesario para evitar llamar a métodos privados para otras clases. Solo se usa para probar que las cosas funcionan realmente.
Lo que en retrospectiva, hace inútiles las protecciones privadas. Si realmente quieres proteger tus métodos, deberás anular el envío para bloquearlos. El siguiente código hace que en base a los private_methods del objeto:
def send_that_blocks_private_methods(method, *args)
if private_methods.include?(method.to_s)
raise "Private method #{method} cannot called be called with send."
else
send_that_allows_private_methods(method, *args)
end
end
alias_method :send_that_allows_private_methods, :send
alias_method :send, :send_that_blocks_private_methods
private :send_that_allows_private_methods
puede especificar un class_variable de private_methods desea bloquear el acceso a su lugar de negar el acceso a todos los métodos privados. También puede hacer que el envío sea privado, pero hay usos legítimos de llamar al envío desde fuera de un objeto.
Tengo curiosidad por saber el razonamiento detrás de las decisiones de diseño también. Mi respuesta es solo una explicación que aclara tus conceptos erróneos. Explica proporcionar un poco del cómo, pero no el por qué. – EmFi