【问题标题】:Ruby Constructors and ExceptionsRuby 构造函数和异常
【发布时间】:2010-12-01 21:21:29
【问题描述】:

Ruby 新手,我正在尝试找出使用什么习语来将某些整数值限制为类的构造函数。

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

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

【问题讨论】:

  • 是的,我对这个问题感到困惑。我是 rescueing 构造函数中的异常,所以按道理应该创建实例。

标签: ruby exception constructor


【解决方案1】:

嗯,即使initialize 引发异常,对象仍然存在是完全正确的。但是,除非您像我刚刚编写的以下代码那样从initialize 中泄漏self,否则任何人都很难坚持引用:

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

【讨论】:

    【解决方案2】:

    使用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 的范围内。

    【讨论】:

      【解决方案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)
      

      【讨论】:

      • 嗯,我将不得不检查我的代码,看看我是否弄错了。感谢您的回答。
      • 实际上,对象 is 已创建,只是 .new 不会返回引用,因此除非对象在 initialize 期间链接到自身,否则它将获得 gc'编辑。
      【解决方案4】:

      如果我没看错你的问题,你想要的是这样的:

      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 方法之前会创建一个实例——如果引发错误,它会被清理掉。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-04-14
        • 2013-05-02
        • 2013-10-01
        • 2016-01-08
        • 1970-01-01
        • 2014-01-05
        • 2011-03-11
        相关资源
        最近更新 更多