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

Tec*_*Zen 5 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 
Run Code Online (Sandbox Code Playgroud)

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

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

>

......效果很好.

但是,如果我要滑倒:

a=Alpha.new("Whoops, a string not a NSURL" )
Run Code Online (Sandbox Code Playgroud)

......它因为来自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>
Run Code Online (Sandbox Code Playgroud)

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

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

mu *_*ort 2

我会尝试转换参数并TypeError在无法转换的情况下提出:

当遇到不属于预期类型的​​对象时引发。

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

引发异常:

TypeError: can't convert String into Integer

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

NSURL在您的特定情况下,尝试通过调用将参数转换为 an to_s,然后NSURL使用该字符串实例化 an (如果他们没有给您一个 )NSURL。我不知道 MacRuby 或相应的 Mac API 的使用方式,因此我对这种特定情况下的明智行为进行了一些猜测,但我认为“转换或引发异常”的想法是合理且明智的。

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