2009-09-28 13 views
9

Nuevo para Ruby, y estoy tratando de averiguar qué idioma usar para restringir algunos valores enteros al constructor de una clase.Ruby Constructors and Exceptions

Por lo que he hecho hasta ahora, si presento una excepción en initialize(), el objeto aún se crea pero estará en un estado no válido (por ejemplo, algunos valores nil en variables de instancia). No puedo ver cómo se supone que debo restringir los valores sin entrar en lo que parece pasos innecesariamente grandes como restringir el acceso al new().

Así que mi pregunta es, ¿por qué mecanismo puedo restringir el rango de valores con el que se crea una instancia de un objeto?

+0

Sí, me confunde a mí mismo en este problema. Estaba 'rescatando' la excepción en el constructor, por lo que es lógico pensar que la instancia se crearía. – Chris

Respuesta

13

Huh, tiene toda la razón de que el objeto sigue vivo incluso si initialize hace una excepción. Sin embargo, será muy difícil para cualquiera de aferrarse a una referencia, a menos de tener fugas self de initialize como el siguiente código que acabo de escribir lo hace:

>> class X 
>> def initialize 
>>  $me = self 
>>  raise 
>> end 
>> def stillHere! 
>>  puts "It lives!" 
>> end 
>> end 
=> nil 
>> t = X.new 
RuntimeError: 
    from (irb):14:in `initialize' 
    from (irb):20:in `new' 
    from (irb):20 
>> t 
=> nil 
>> $me 
=> #<X:0xb7ab0e70> 
>> $me.stillHere! 
It lives! 
3

no estoy seguro acerca de esta declaración:

De lo que he hecho hasta ahora, si levanto una excepción en initialize(), el objeto todavía se crea, pero estaré en un estado inválido (por ejemplo, algunos valores nulos en variables de instancia).

class Foo 

    def initialize(num) 
    raise ArgumentError.new("Not valid number") if num > 1000 
    @num = num 
    end 

end 

f = Foo.new(4000) #=> n `initialize': not valid (RuntimeError) 
+0

Hmm, voy a tener que revisar mi código y ver si me equivoco. Gracias por la respuesta. – Chris

+1

En realidad, el objeto * es * creado, es solo que .new no devolverá la referencia, por lo que a menos que el objeto se vincule a sí mismo durante 'initialize' obtendrá gc'ed. – DigitalRoss

2

Si estoy leyendo bien su pregunta, lo que quiere decir algo como esto:

class SerialNumber 
    VALID_SERIAL_NUMBERS = (0..10,000,000,000) 
    def initialize(n) 
    raise ArgumentError.new("Serial numbers must be positive integers less than 10 Billion") unless VALID_SERIAL_NUMBERS.include?(n) 
    @n = n 
    end 
end 

No se preocupe que SerialNumber.new crea una instancia antes de que se llama método initialize - se limpiará si se produce un error.

0

El uso del validatable module parece una muy buena opción en el contexto.

Aquí es un ejemplo de cómo usarlo:

class Person 
    include Validatable 
    validates_numericality_of :age 
    end 

para hacer un sólo números en un rango particular, sería:

class Person 
    include Validatable 
    validates_numericality_of :age 
    validates_true_for :age, :logic => lambda { (0..100).include?(age) } 
    end 

Por supuesto, esto validará que la edad está dentro de el rango de 0 y 100.