Ruby构造函数和异常

时间:2009-09-28 02:12:39

标签: ruby exception constructor

Ruby的新手,我正在试图找出用于将某些整数值限制为类的构造函数的习惯用法。

从我到目前为止所做的,如果我在initialize()中引发异常,该对象仍然被创建但是将处于无效状态(例如,实例变量中的某些nil值)。我不太明白我应该如何限制这些值,而不会进入看起来不必要的大步骤,例如限制对new()的访问。

所以我的问题是,通过什么机制可以限制对象实例化的值的范围?

4 个答案:

答案 0 :(得分:13)

嗯,即使initialize引发异常,对象仍然存在,这是完全正确的。但是,任何人都很难挂起引用,除非你从self中泄漏initialize,就像我刚刚编写的代码那样:

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

答案 1 :(得分:3)

我不确定这句话:

  

从我到目前为止所做的,如果我加注   在initialize()中有一个例外   对象仍然被创建但将在   一个无效的状态(例如,一些   实例变量中的nil值。)

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)

答案 2 :(得分:2)

如果我正确地阅读你的问题,你想要的是这样的:

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

不要担心SerialNumber.new在调用initialize方法之前创建一个实例 - 如果出现错误,它将被清理。

答案 3 :(得分:0)

使用validatable module似乎非常适合上下文。

以下是如何使用它的示例:

  class Person
    include Validatable
    validates_numericality_of :age
  end

如果仅在特定范围内进行数字,则为:

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

这当然会验证年龄是否在0到100之间。