Existen dos elementos diferentes de este comportamiento. La primera es almacenar x
en un valor de solo lectura, y la segunda es protegiendo el getter de ser alterado en subclases.
de sólo lectura valor
Es posible en Ruby para almacenar los valores de sólo lectura en tiempo de inicialización. Para hacer esto, usamos el comportamiento de cierre de los bloques de Ruby.
class Foo
def initialize (x)
define_singleton_method(:x) { x }
end
end
El valor inicial de x
está ahora bloqueado en el interior del bloque se utilizó para definir el getter #x
y nunca se puede acceder excepto llamando foo.x
, y nunca puede ser alterado.
foo = Foo.new(2)
foo.x # => 2
foo.instance_variable_get(:@x) # => nil
en cuenta que no se almacena como la variable de instancia @x
, sin embargo, todavía está disponible a través del captador hemos creado usando define_singleton_method
.
Protección del comprador
En Rubí, casi cualquier método de cualquier clase se pueden sobrescribir en tiempo de ejecución. Hay una forma de evitar esto utilizando el gancho method_added
.
class Foo
def self.method_added (name)
raise(NameError, "cannot change x getter") if name == :x
end
end
class Bar < Foo
def x
20
end
end
# => NameError: cannot change x getter
Este es un método muy severo para proteger el captador.
Requiere que se añade cada captador protegido al method_added
gancho de forma individual, y aún así, se tendrá que añadir otro nivel de protección a method_added
Foo
y sus subclases para evitar un codificador de sobrescribir el método method_added
sí.
Es mejor aceptar que el reemplazo de código en tiempo de ejecución es una realidad cuando se usa Ruby.
Esto parece una solicitud poco común, ¿cuál es el caso de uso para un patrón así? Quizás sabes algo que yo no sé, que sería útil en el futuro. –
Viniendo del mundo C++, me parece natural tener variables privadas en la clase base a las que no se puede acceder en la clase derivada y me da la seguridad de que no se modificarán en la clase derivada. En el ejemplo anterior, puedo estar seguro de que el único lugar donde se modificará @x es en la clase "Base" si es posible convertirlo en una variable de instancia privada. – prasadvk
¿Podría darme un caso de uso más específico para él? No tiene por qué ser complicado. Siento que si entendí un problema para el cual no quisiera que un objeto tuviera acceso a sus propios espacios, podría ayudar a la discusión. –