2012-01-05 52 views
42

Estoy aprendiendo a programar y he decidido probar Ruby. Estoy seguro de que esta es una pregunta estúpida, pero el instructor está hablando de métodos setter y getter, y estoy confundido. Aquí está el ejemplo:Tratando de aprender/entender los métodos de Ruby setter y getter

class Human 
    def noise=(noise) 
    @noise = noise 
    end 

    def noise 
    @noise 
    end 
end 

partir de esto, la clase se crea una instancia, y puedo pone esto:

man = Human.new 
man.noise=("Howdie!") 
puts man.noise 

Esto se traduce en Howdie!

Ahora lo que me confunde es que el instructor está diciendo que sin el método getter (el segundo de los dos métodos), no hay forma de interactuar con la variable de instancia @noise.

Pero cuando quito el método getter, soy capaz de seguir teniendo acceso @noise, ver ejemplo:

class Human 
    def noise=(noise) 
    @noise = noise 
    end 
end 

man = Human.new 
puts man.noise=("Howdie!") 

Esto funciona igual que cuando se utiliza el método de obtención.

Así que ahora estoy confundido. ¿Por qué es necesario el getter? ¿Qué quiere decir el instructor al no poder acceder a la variable de instancia sin él? ¿Es posible que esté usando una versión anterior de Ruby?

Gracias de antemano por su ayuda.

+0

¿Realmente puede acceder a @noise, o es lo que está viendo un efecto secundario de la función que está llamando ... – LVB

Respuesta

31

se puede interactuar con la variable de instancia de otros métodos que pertenecen a esa instancia, incluso si no hay un captador:

def noise=(noise) 
    @noise = noise 
end 

def last_noise 
    @noise 
end 

No tiene por qué ser un captador definida con el mismo nombre que el método ; los dos no están vinculados en absoluto. El getter es necesario para "obtener" el valor de la variable de instancia, pero solo en una sintaxis corta.

lo que está sucediendo en su ejemplo es que estás inicializar un nuevo objeto (Human.new), y luego usando un método (noise=, sí el nombre del método contiene el símbolo =) que se acaba tan ocurre para definir una variable de instancia (es decir, una variable solo para esa instancia), y finalmente recuperando esa variable de instancia con otra llamada al método.

En realidad se puede utilizar instance_variable_get para obtener la variable de instancia, sin definir ninguna captador en absoluto:

man = Human.new 
man.noise = "Howdie" 
man.instance_variable_get("@noise") 

Esto devolverá "Howdie", a pesar de que no hay ningún comprador definido.

Y no, no creo que esté usando una versión anterior de Ruby.

+2

+1 Ryan. Como de costumbre, su experiencia es excelente y no sabía sobre instance_variable_get! –

+0

hey que no anula attr_protected ¿verdad? –

+0

Respondí mi propia pregunta: - api dice "Los atributos nombrados en esta macro están protegidos de la asignación masiva" –

14

La línea de código

puts man.noise=("Howdie!") 

no utiliza el método de obtención, por lo que el método getter no necesita ser definida para que funcione. Esa línea solo usa el método setter. El valor de retorno del método setter es automáticamente igual a lo que esté en el lado derecho del signo igual, entonces "Howdie!" pasa a puts.

La línea de código

puts man.noise 

usa el método de obtención, y que no funcionaría si se quita el método getter.

+0

Así que supongo que mi pregunta es, ¿por qué utilizar los métodos getter & setter? ¿Por qué no usar el método setter (o el método básico que me permite pasarle un valor al método) y tener un "retorno" sobre eso? No estoy sugiriendo una mejor manera de hacer las cosas, realmente estoy preguntando por qué? No entiendo. – Nathan

+1

Necesita el método getter porque a veces desea obtener el valor de la variable sin cambiarla. El método setter siempre establece el valor en algo, por lo que es imposible usar el método setter para obtener el valor sin modificarlo. –

+0

Solo necesita el método getter si desea que la variable sea legible por métodos fuera de la clase. Si solo quiere leer la variable de un método de la clase, simplemente puede usar '@ noise' en lugar del método getter. –

5

Seguramente ambos devuelven un valor, pero su comportamiento es diferente.

Digamos que ya hay un miembro @a.

con getter, uno obtiene el valor actual de @a, sin modificarlo.

con setter, uno modifica @a, y obtiene su nuevo valor como valor de retorno.

cuando se piensa en el comportamiento del organismo, tenga en cuenta:

  1. el antiguo valor de @ un no se puede obtener con el organismo, y consiguió sobrescribe.

  2. lo devuelto por setter, en realidad ya se conoce antes de invocar el setter.

+0

No entendí tu respuesta hasta que leí la de los demás , ahora que lo hice (y pensé un poco más), creo que tu respuesta me ayuda a aclarar la pregunta que tenía. Si refuerzas tu respuesta para que se reduzca la necesidad de que los novatos como yo lean primero las respuestas de todos los demás, entonces me gustaría seleccionar la tuya. – Nathan

+0

contento de haber ayudado;) – Jokester

1

Puede ser que la atención para getters y setters se deba a que algunos otros idiomas le permiten acceder directamente a las variables de clase. Python:

class k: 
    i = 100 

print k.i # 100 
k.i = 200 
print k.i # 200 

Por el contrario, Ruby mantiene todas sus variables completamente privadas a la clase y sólo los expone a través de métodos de acceso.

En su ejemplo, si elimina el captador, puede interactuar con la variable (es decir, cambiarla) a través del colocador, pero no puede recuperarla (de forma regular) cuando la necesita .

Cuestiones relacionadas