我在Ruby中知道我可以使用respond_to?
检查一个对象是否有某种方法。
但是,鉴于课程,我如何检查实例是否有某种方法?
,比如
Foo.new.respond_to?(:bar)
但我觉得必须有一种比实例化新实例更好的方法。
答案 0 :(得分:345)
我不知道为什么每个人都建议您在instance_methods
完成工作时使用include?
和method_defined?
。
class Test
def hello; end
end
Test.method_defined? :hello #=> true
答案 1 :(得分:43)
您可以按如下方式使用method_defined?
:
String.method_defined? :upcase # => true
比其他人似乎暗示的instance_methods.include?
更容易,更轻松,更有效率。
请记住,您不会知道某个类是否动态响应某些使用method_missing
的调用,例如重新定义respond_to?
,或者因为Ruby 1.9.2定义了respond_to_missing?
答案 2 :(得分:22)
实际上这对于对象和类都不起作用。
这样做:
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
答案 3 :(得分:8)
“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,那么添加逻辑来搜索字符串和符号也是一个方便的地方。
答案 4 :(得分:3)
不确定这是否是最佳方法,但您可以随时执行此操作:
Foo.instance_methods.include? 'bar'
答案 5 :(得分:3)
尝试Foo.instance_methods.include? :bar
答案 6 :(得分:2)
如果您正在检查对象是否可以响应一系列方法,您可以执行以下操作:
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。
答案 7 :(得分:2)
我认为Rails中的method_defined?
有问题。它可能是不一致的,所以如果你使用Rails,最好使用attribute_method?(attribute)
中的内容。
“testing for method_defined? on ActiveRecord classes doesn't work until an instantiation”是关于不一致的问题。
答案 8 :(得分:1)
klass.instance_methods.include :method_name
或"method_name"
,具体取决于我认为的Ruby版本。
答案 9 :(得分:1)
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]
希望这能帮到你!
答案 10 :(得分:1)
虽然respond_to?
仅对公共方法返回true,但是检查类上的“方法定义”也可能与私有方法有关。
在Ruby v2.0 +上,可以通过以下方式同时检查公共集和私有集:
Foo.private_instance_methods.include?(:bar) || Foo.instance_methods.include?(:bar)
答案 11 :(得分:0)
在我使用ruby 2.5.3的情况下,以下句子非常有效:
value = "hello world"
value.methods.include? :upcase
它将返回布尔值true或false。