处理由于传递无效的初始化参数而导致对象无法初始化的情况的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中的异常,还是有更优雅的解决方案?我是红宝石的菜鸟,所以假设我从错误的角度来看待这个问题。
答案 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文档中使用的行为。