我知道在Ruby中我可以使用respond_to?
来检查一个对象是否有一个特定的方法。给定一个类,看看实例是否有方法(红宝石)
但是,给定类,如何检查实例是否具有某种方法?
即,像
Foo.new.respond_to?(:bar)
但我觉得有一定有比实例化一个新的实例更好的办法。
我知道在Ruby中我可以使用respond_to?
来检查一个对象是否有一个特定的方法。给定一个类,看看实例是否有方法(红宝石)
但是,给定类,如何检查实例是否具有某种方法?
即,像
Foo.new.respond_to?(:bar)
但我觉得有一定有比实例化一个新的实例更好的办法。
我不知道为什么每个人都建议你应该使用instance_methods
和include?
当method_defined?
做这项工作。
class Test
def hello; end
end
Test.method_defined? :hello #=> true
对“Given a class, see if instance has method (Ruby)”的回答比较好。显然Ruby有这个内置的,我不知何故错过了它。无论如何,我的答案留作参考。
Ruby类别响应方法instance_methods
和public_instance_methods
。在Ruby 1.8中,第一个列出了字符串数组中的所有实例方法名称,第二个将它限制为公共方法。第二种行为是你最想要的,因为默认情况下,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,这将是一个方便的地方添加搜索字符串和符号的逻辑。
klass.instance_methods.include :method_name
或"method_name"
,这取决于我认为的Ruby版本。
不知道这是最好的方式,但你总是可以做到这一点:
Foo.instance_methods.include? 'bar'
尝试Foo.instance_methods.include? :bar
您可以使用method_defined?
如下:
String.method_defined? :upcase # => true
容易得多,比其他人似乎暗示的instance_methods.include?
便携和高效。
请记住,你不会知道,如果一个类重新定义respond_to?
动态响应某些呼叫与method_missing
,例如,或自从红宝石1.9.2定义respond_to_missing?
。
请注意,如果您手头有实例并且您不知道它是类,则可以执行'instance .class.method_defined? :upcase' – jaydel 2016-10-20 12:55:14
实际上,这对于对象和类都不起作用。
这并不:
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
例如,你也可以使用'instance.class.method_defined?' – Luksurious 2013-10-12 15:16:23
这取决于你的红宝石版本。上述方法适用于所有版本,包括1.8.7。 – 2013-10-16 23:36:35
如果你检查是否一个对象可以为一系列的应对方法,你可以这样做:
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
在这种情况下,你想使用的符号,因为当你调用。方法,它返回符号数组,如果你使用["my", "methods"]
,它'返回假。
我认为在Rails中有method_defined?
有问题。它可能不一致或者其他,所以如果你使用Rails,最好使用attribute_method?(attribute)
。
“testing for method_defined? on ActiveRecord classes doesn't work until an instantiation”是关于不一致的问题。
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]
希望这可以帮助你!
最简单的答案ftw – user94154 2010-07-22 15:00:51
method_defined?是最好的解决方案,因为instance_methods在Ruby 1.8和1.9之间改变。 1.8返回一个字符串数组,1.9返回一组符号。 method_defined?在1.8和1.9中都有一个符号。 – Jason 2012-05-02 17:03:26
更不用说:instance_methods会在每次调用时创建一个新数组,并且:include?然后将不得不走阵列告诉。相反,:method_defined?将在内部查询方法查找表(一个用C语言进行的哈希查找),并让您知道而不创建任何新对象。 – Asher 2013-07-12 00:40:07