我知道在Ruby中,我可以使用respond_to?检查一个对象是否有特定的方法。

但是,给定类,我如何检查实例是否有特定的方法?

比如,就像

Foo.new.respond_to?(:bar)

但我觉得肯定有比实例化一个新实例更好的方法。


当前回答

我不知道为什么每个人都建议你应该使用instance_methods和include?当method_defined ?完成任务。

class Test
  def hello; end
end

Test.method_defined? :hello #=> true

NOTE

如果你是从其他OO语言来的Ruby,或者你认为method_defined的意思是你显式定义的方法:

def my_method
end

然后读这个:

在Ruby中,模型上的属性基本上也是一个方法。所以method_defined ?对于属性也将返回true,而不仅仅是方法。

例如:

给定一个具有String属性first_name的类实例:

<instance>.first_name.class #=> String

<instance>.class.method_defined?(:first_name) #=> true

因为first_name既是一个属性也是一个方法(也是一个string类型的字符串)。

其他回答

不确定这是否是最好的方法,但你总是可以这样做:

Foo.instance_methods.include? 'bar'

klass.instance_methods。包括:method_name或"method_name",我认为这取决于Ruby版本。

如果你正在检查一个对象是否可以响应一系列的方法,你可以这样做:

methods = [:valid?, :chase, :test]

def has_methods?(something, methods)
  methods & something.methods == methods
end

方法等等。方法将在它们的公共/匹配元素上连接两个数组。某物Methods包含你要检查的所有方法,它等于Methods。例如:

[1,2] & [1,2,3,4,5]
==> [1,2]

so

[1,2] & [1,2,3,4,5] == [1,2]
==> true

在这种情况下,你会想要使用符号,因为当你调用。methods时,它会返回一个符号数组,如果你使用["my", "methods"],它会返回false。

实际上,这并不适用于对象和类。

这样做:

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

你可以使用method_defined?如下:

String.method_defined? :upcase # => true

比instance_methods.include?其他人似乎都在建议。

请记住,你不会知道一个类是否动态响应一些调用method_missing,例如通过重新定义respond_to?,或者从Ruby 1.9.2开始定义respond_to_missing?。