我非常喜欢Ruby,但我对如何实现接口感到困惑。在下面显示的示例中,类A在对象上调用方法get_data
,该对象作为构造函数参数传入。确保obj
具有正确类型并实现方法get_data
的最佳做法是什么?我见过的代码只是"指定了所需的接口"在类的initialize
方法的RDoc中:"参数必须包含模块Bar","参数必须是Blah"或"参数必须有方法' get_data'"。是否有更好的程序化方式?
class A
def initialize(obj)
@obj = obj
end
def foo
# Do something with @obj
var = @obj.get_data
...
end
end
答案 0 :(得分:1)
我认为您所看到的是依赖注入,而不是在您的方法SomeClass.new.get_data
foo
A类具有信任级别,初始化A的对象应该传递参数,这是SomeClass的对象,就像这样。
object_a = A.new(SomeClass.new)。
因此,如果您想明确检查@obj是否可以回复邮件get_data
,您可以使用ruby' s respond_to?(:method_name)
所以你的代码变成了这个
def foo
# Do something with @obj
if @obj.respond_to?(:get_data)
var = @obj.get_data
end
...
end
答案 1 :(得分:-1)
Ruby是一种动态类型的语言,它也是鸭子类型,当你决定使用鸭子打字功能时,你应该在文档中提及它并调用它,如果它不存在它会崩溃,仔细想想,假装你可以检查fsync()
是否存在(你可以在后面看到),你想做什么?
您要退回get_data
吗?如果nil
应该返回一个值,您可以返回foo
,但如果nil
意图返回任何内容(语义无效),那么您将为用户带来NoSuchMethodError for nil:NilClass
的风险foo
不是你的选择,你想nil
出错吗?很可能你想检查raise
存在的原因是为了防止类型错误,但是现在你又引发了一个错误,也许你想提出一个特定的错误,但老实说get_data
在我看来是特定的。
在我的脑海里,我会告诉你如何检查它,有很多方法,一个非常简单的方法:
NoSuchMethodError : method get_data missing in someObject:SomeClass
可能更好的方法是使用上述方式检查def foo
begin
var = @obj.get_data
rescue NoMethodError
// handle the case where get_data does not exist
end
end
obj
中get_data
是否initialize
:
def initialize(obj)
if(!obj.respond_to? :get_data)
//handle the case where get_data is not defined
end
end
最后一个代码的问题是,您检查的所有内容都是obj
get_data
,如果您想检查是否可以,请不要检查是否有正确的签名:< / p>
def initialize(obj)
unless(!obj.respond_to? :get_data)
params = obj.method(:get_data).parameters
//if get_data for example takes x,y then params will be `[[:req,:x],[:req,:y]]`
end
end
当然,您无法检查get_data是否接受特定类型,因为ruby是动态类型的。
如果您还想检查方法的存在和参数后检查方法的返回类型,可以调用它,因为它是安全的并检查返回类型如下:
a=obj.get_data
if(a.is_a? SomeClass)
//good
end
如果你想检查get_data什么都不返回(语义上是无效的方法),那么ruby返回nil
类似于void,但是返回一个值也是如此,所以你不能检查它