2011-01-09 13 views
8

Me gustaría cambiar el valor propio de una instancia de float.Ruby y auto modificante para una instancia de Float

tengo el siguiente método:

class Float 
    def round_by(precision) 
    (self * 10 ** precision).round.to_f/10 ** precision 
    end 
end 

Y me gustaría añadir el round_by! método que modificará el valor propio.

class Float 
    def round_by!(precision) 
    self = self.round_by(precision) 
    end 
end 

Pero recibí un error que decía que no podía cambiar el valor de mí mismo.

¿Alguna idea?

+2

¿Te imaginas si llamar 'x = 13.2; x.round! 'provocó que todos los valores de' 13.2' de tu aplicación se convirtieran en '13'? Qué desafortunado sería eso. – Phrogz

Respuesta

10

No puede cambiar el valor de self. Siempre apunta al objeto actual, no puede hacer que apunte a otra cosa.

Cuando desee modificar el valor de un objeto, puede hacerlo llamando a otros métodos de mutación o estableciendo o cambiando los valores de las variables de instancia, no intentando reasignar self. Sin embargo, en este caso, eso no lo ayudará, porque Float no tiene ningún método de mutación, y el establecimiento de variables de instancia no le comprará nada, porque ninguna de las variables de instancia afecta a ninguna de las operaciones de flotación predeterminadas.

Así que la conclusión es: no se pueden escribir métodos de mutación en flotadores, al menos no de la manera que se desee.

0

Esto es realmente una muy buena pregunta y lamento decir que no se puede, al menos no con la clase Float. Es inmutable Mi sugerencia sería la creación de su propia clase de los implementos flotador (aka hereda todos los métodos), al igual que en el pseudo-código

class MyFloat < Float 
    static CURRENT_FLOAT 

    def do_something 
    CURRENT_FLOAT = (a new float with modifications) 
    end 
end 
+0

¡Gracias por el truco! – Arkan

+2

No estoy seguro de qué 'static CURRENT_FLOAT' se supone que debe hacer, pero definitivamente no lo hace. Además, 'CURRENT_FLOAT' es una constante y, por lo tanto, no debe reasignarse. Probablemente quiera usar una variable de instancia ('@') en su lugar. Además, dado que la clase 'Float' en realidad permite variables de instancia (ya que a diferencia de Fixnum no es un valor inmediato y por lo tanto no es técnicamente inmutable), en realidad no es necesario subclasificar Float para hacer esto, solo puede parchearlo. Sin embargo, si eso es recomendable es otro problema (de hecho, tampoco lo recomendaría y simplemente no definiría un método mutable). – sepp2k

+0

la idea era crear una variable estática de la clase que sea un objeto flotante y luego cada vez que use un método bang, cree un nuevo float y establézcalo en current_float, de ahí que sea destructivo – sethvargo

1

También puede crear una clase y almacenar el flotador en una variable de instancia:

class Variable 

    def initialize value = nil 
    @value = value 
    end 

    attr_accessor :value 

    def method_missing *args, &blk 
    @value.send(*args, &blk) 
    end 

    def to_s 
    @value.to_s 
    end 

    def round_by(precision) 
    (@value * 10 ** precision).round.to_f/10 ** precision 
    end 

    def round_by!(precision) 
    @value = round_by precision 
    end 
end 

a = Variable.new 3.141592653 

puts a   #=> 3.141592653 

a.round_by! 4 

puts a   #=> 3.1416 

Más sobre el uso de "class Variable" here.

Cuestiones relacionadas