10 Stimmen

Ruby-Konstruktoren und Ausnahmen

Neu in Ruby, und ich versuche, herauszufinden, welches Idiom zu verwenden, um einige Integer-Werte auf den Konstruktor einer Klasse zu beschränken.

Nach dem, was ich bisher getan habe, wenn ich eine Ausnahme in initialize() wird das Objekt zwar erstellt, befindet sich aber in einem ungültigen Zustand (z. B. einige nil Werte in Instanzvariablen). Ich kann nicht ganz erkennen, wie ich die Werte einschränken soll, ohne unnötig große Schritte zu machen, wie z. B. den Zugriff auf new() .

Also meine Frage ist, durch welchen Mechanismus kann ich den Bereich der Werte ein Objekt instanziiert mit einschränken?

14voto

DigitalRoss Punkte 138823

Sie haben völlig recht, dass das Objekt auch dann noch lebt, wenn initialize löst eine Ausnahme aus. Es wird jedoch ziemlich schwer für jemanden sein, an einer Referenz festzuhalten, es sei denn, Sie lassen self aus initialize wie der folgende Code, den ich gerade geschrieben habe:

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

4voto

khelll Punkte 22794

Ich bin mir bei dieser Aussage nicht sicher:

Nach dem, was ich bisher getan habe eine Ausnahme i Objekt immer noch erstellt, aber es wird in einem ungültigen Zustand (zum Beispiel ein ungültige Werte in Instanzvariablen).

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)

2voto

James A. Rosen Punkte 62226

Wenn ich Ihre Frage richtig verstehe, wollen Sie etwas in dieser Art:

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

Machen Sie sich keine Sorgen, dass SerialNumber.new vorher eine Instanz erzeugt initialize Methode aufgerufen wird - sie wird bereinigt, wenn der Fehler auftritt.

0voto

jkupferman Punkte 610

Die Verwendung des validierbares Modul scheint wirklich gut in den Kontext zu passen.

Hier ist ein Beispiel für die Verwendung:

  class Person
    include Validatable
    validates_numericality_of :age
  end

Für die Berechnung von Zahlen nur in einem bestimmten Bereich wäre dies der Fall:

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

Dadurch wird natürlich bestätigt, dass das Alter im Bereich zwischen 0 und 100 liegt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X