给定一个类,看看实例是否有方法(Ruby)
我知道在Ruby中,我可以使用respond_to?
检查一个对象是否有一定的方法。
但是,给定类,如何检查实例是否有一定的方法?
即类似的东西
Foo.new.respond_to?(:bar)
但是我觉得要比实例化一个新实例更好。
我不知道为什么每个人都build议你应该使用instance_methods
并include?
何时method_defined?
做这个工作。
class Test def hello; end end Test.method_defined? :hello #=> true
你可以使用method_defined?
如下:
String.method_defined? :upcase # => true
比instance_methods.include?
更容易,便携和高效instance_methods.include?
其他人似乎都在暗示。
请记住,您将不知道某个类是否通过method_missing
dynamic响应某些调用,例如通过重新定义respond_to?
或者从Ruby 1.9.2开始,通过定义respond_to_missing?
。
实际上这不适用于对象和类。
这样做:
class TestClass def methodName end end
所以给出的答案,这是有效的:
TestClass.method_defined? :methodName # => TRUE
但是这不起作用:
t = TestClass.new t.method_defined? : methodName # => ERROR!
所以我使用这个类和对象:
类别:
TestClass.methods.include? 'methodName' # => TRUE
对象:
t = TestClass.new t.methods.include? 'methodName' # => TRUE
“ 给定一个类,看实例是否有方法(Ruby) ”的答案比较好。 Ruby显然有这个内置的,我不知何故错过了它。 无论如何,我的答案留给参考。
Ruby类对方法instance_methods
和public_instance_methods
作出响应。 在Ruby 1.8中,第一个列出了string数组中的所有实例方法名,第二个将其限制为公共方法。 第二个行为是你最想要的,因为respond_to?
也违反了公共方法。
Foo.public_instance_methods.include?('bar')
但在Ruby 1.9中,这些方法返回符号数组。
Foo.public_instance_methods.include?(:bar)
如果您打算经常这样做,则可能需要扩展Module
以包含快捷方式。 (将它分配给Module
而不是Class
可能看起来很奇怪,但是因为这是instance_methods
方法的存在,所以最好保持与该模式一致。)
class Module def instance_respond_to?(method_name) public_instance_methods.include?(method_name) end end
如果你想同时支持Ruby 1.8和Ruby 1.9,那么添加逻辑来searchstring和符号也是一个很方便的地方。
不知道这是否是最好的方法,但你可以一直这样做:
Foo.instance_methods.include? 'bar'
如果你正在检查一个对象是否可以响应一系列的方法,你可以这样做:
methods = [:valid?, :chase, :test] def has_methods?(something, methods) methods & something.methods == methods end
methods & something.methods
将在它们的公共/匹配元素上连接这两个数组。 something.methods包括所有你正在检查的方法,它将等于方法。 例如:
[1,2] & [1,2,3,4,5] ==> [1,2]
所以
[1,2] & [1,2,3,4,5] == [1,2] ==> true
在这种情况下,你会想要使用符号,因为当你调用.methods时,它将返回一个符号数组,如果你使用["my", "methods"]
,它会返回false。
试试Foo.instance_methods.include? :bar
Foo.instance_methods.include? :bar
我认为method_defined?
在Rails中。 这可能是不一致的,所以如果你使用Rails,最好使用attribute_method?(attribute)
。
“ 在实例化之前,对ActiveRecord类的method_defined进行testing是不可行的 ”,这是一个关于不一致性的问题。
klass.instance_methods.include :method_name
或"method_name"
,这取决于我认为的Ruby版本。
class Foo def self.fclass_method end def finstance_method end end foo_obj = Foo.new foo_obj.class.methods(false) => [:fclass_method] foo_obj.class.instance_methods(false) => [:fclass_method]
希望这可以帮助你!