Constructori și excepții Ruby (Programare, Ruby, Excepție, Constructor)

Chris a intrebat.

Sunt nou în Ruby și încerc să-mi dau seama ce idiom să folosesc pentru a restricționa unele valori întregi la constructorul unei clase.

Din ceea ce am făcut până acum, dacă ridic o excepție în initialize(), , obiectul este în continuare creat, dar va fi într-o stare invalidă (de exemplu, unele nil valori în variabilele de instanță). Nu prea îmi dau seama cum ar trebui să restricționez valorile fără a intra în pași care par inutil de mari, cum ar fi restricționarea accesului la new().

Așadar, întrebarea mea este: prin ce mecanism pot restricționa intervalul de valori cu care un obiect este instanțiat?

Comentarii

  • Da, m-am încurcat în această problemă. Am fost rescueing excepția în constructor, deci este logic că instanța ar fi creată. –  > Por Chris.
4 răspunsuri
DigitalRoss

Huh, aveți perfectă dreptate că obiectul trăiește în continuare chiar dacă initialize ridică o excepție. Cu toate acestea, va fi destul de greu pentru oricine să se agațe de o referință, cu excepția cazului în care se scurge self din initialize așa cum face următorul cod pe care tocmai l-am scris:

>> 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!

khelll

Nu sunt sigur de această afirmație:

Din ceea ce am făcut până acum, dacă ridic o excepție în initialize(), obiectul este în continuare creat, dar va fi într-o stare invalidă (de exemplu, niște valori nule în variabilele de instanță).

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)

Comentarii

  • Hmm, va trebui să-mi revizuiesc codul și să văd dacă nu cumva mă înșel. Mulțumesc pentru răspuns. –  > Por Chris.
  • De fapt, obiectul este creat, doar că .new nu returnează referința, așa că, dacă obiectul nu se leagă de el însuși în timpul initialize acesta va fi gc’ed. –  > Por DigitalRoss.
James A. Rosen

Dacă vă citesc corect întrebarea, ceea ce doriți este ceva de genul următor:

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

Nu vă faceți griji că SerialNumber.new creează o instanță înainte de asta. initialize metoda este apelată – va fi curățată în cazul în care eroarea este ridicată.

jkupferman

Folosind metoda modulul validatable pare să se potrivească foarte bine în acest context.

Iată un exemplu de utilizare a acestuia:

  class Person
    include Validatable
    validates_numericality_of :age
  end

Pentru a face un număr numai într-un anumit interval, ar fi:

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

Acest lucru va valida, desigur, faptul că vârsta este cuprinsă între 0 și 100.