Ruby:如何处理失败或无效的初始化

时间:2011-05-14 02:34:26

标签: ruby exception-handling initialization macruby

处理由于传递无效的初始化参数而导致对象无法初始化的情况的ruby最佳实践是什么?

我意识到在红宝石中,鸭子打字意味着我们不应该过分关注变量/参数类型,而是关注它们的行为方式。但是,我在MacRuby中工作,它通过Cocoa Objective-C API进行桥接,一些Cocoa方法需要类型参数。

例如,我有一个调用Objective-C API的ruby类,并且必须将它传递给NSURL类的对象。它看起来像这样:

class Alpha
  attr_accessor :model
  def initialize(hopefully_a_NSURL)
    # bridged from Objective-C API
    @model=NSManagedObjectModel.alloc.initWithContentsOfURL(hopefully_a_NSURL)    
  end # initialize  
end 

......我会这样称呼它:

#bridged from Objective-C API
u=NSURL.fileURLWithPath(p)
a=Alpha.new(u)
puts "a=#{a.model}" # => a=#<NSManagedObjectModel:0x2004970e0

&GT;

......效果很好。

然而,如果我要滑倒:

a=Alpha.new("Whoops, a string not a NSURL" )

...它充斥着来自Objective-C API深处的错误。

当然,我可以进行测试,以防止错误的参数到达桥接对象:

class Alpha
  attr_accessor :model
  def initialize(hopefully_a_NSURL)
    if hopefully_a_NSURL.class==NSURL
      @model=NSManagedObjectModel.alloc.initWithContentsOfURL(hopefully_a_NSURL) 
    end   
  end # initialize  
end 


u=NSURL.fileURLWithPath(p)
a=Alpha.new("")
puts "a=#{a}" # => a=#<Alpha:0x200399160>

...但我仍然得到一个实时实例。我甚至尝试从初始化返回nil,但似乎ruby坚持总是返回一个实例。

我读到的所有内容都表明类型检查在ruby中非常不受欢迎,但在MacRuby的情况下,我可能不得不例外。这可以很好地利用ruby中的异常,还是有更优雅的解决方案?我是红宝石的菜鸟,所以假设我从错误的角度来看待这个问题。

1 个答案:

答案 0 :(得分:1)

如果无法进行转换,我会尝试转换参数并引发TypeError

  

遇到不符合预期类型的​​对象时触发。

     

[1, 2, 3].first("two")

     

提出异常:

     

TypeError: can't convert String into Integer

Ruby核心和标准库可以做到这一点,所以没有理由你也做不到。当您执行不应该执行的操作时,Ruby核心将引发异常(调用不受支持的方法,调用具有错误数量的参数的方法,......)因此抛出TypeError会有意义。而且,如果TypeError不合适,则总是ArgumentError

在您的特定情况下,尝试通过调用NSURL将参数转换为to_s,然后使用该字符串实例化NSURL,如果他们没有给您{{1} }}。我不知道我的方式围绕MacRuby或相应的Mac API,所以我有点猜测在这个特定情况下的明智行为,但我认为“转换或提出异常”的想法是合理和明智的。

当然,您也应该记录您将在API文档中使用的行为。