给定一个类,看看实例是否有方法(Ruby)

use*_*154 219 ruby respond-to

我在Ruby中知道我可以respond_to?用来检查对象是否有某种方法.

但是,鉴于课程,我如何检查实例是否有某种方法?

即,像

Foo.new.respond_to?(:bar)
Run Code Online (Sandbox Code Playgroud)

但我觉得有必要比实例化一个新实例更好的方法.

hor*_*guy 356

我不知道为什么每个人都建议你应该使用instance_methods,include?什么时候method_defined?工作.

class Test
  def hello; end
end

Test.method_defined? :hello #=> true
Run Code Online (Sandbox Code Playgroud)

  • method_defined?是最好的解决方案,因为instance_methods在Ruby 1.8和1.9之间发生了变化.1.8返回一个字符串数组,1.9返回一个符号数组.method_defined?在1.8和1.9中都有一个符号. (9认同)
  • 虽然这样使用它时至少有一个优点,`String.instance_methods(false).include?:freeze`,**false**参数可以准确判断是否在String类中定义了`freeze`方法.在这种情况下,它将返回false,因为`freeze`方法是通过String从内核模块继承的,但是`String.method_defined?:freeze`将始终返回true,这对此目的无济于事. (4认同)
  • 更不用说:instance_methods将在每次调用时创建一个新数组,并且:include?然后必须走数组来告诉.相比之下,:method_defined?将在内部查询方法查找表(C中的一个哈希查找),并在不创建任何新对象的情况下通知您. (2认同)

Mar*_*une 45

您可以使用method_defined?如下:

String.method_defined? :upcase # => true
Run Code Online (Sandbox Code Playgroud)

instance_methods.include?其他人似乎更容易,便携和高效.

请记住,您不会知道某个类是否动态响应某些调用method_missing,例如通过重新定义respond_to?,或者通过定义来自Ruby 1.9.2 respond_to_missing?.

  • 注意,如果手头有一个实例,但您不知道它是类,则可以执行instance.class.method_defined?:upcase` (2认同)

Ale*_*x V 24

实际上这对于对象和类都不起作用.

这样做:

class TestClass
  def methodName
  end
end
Run Code Online (Sandbox Code Playgroud)

因此,通过给定的答案,这可行:

TestClass.method_defined? :methodName # => TRUE
Run Code Online (Sandbox Code Playgroud)

但这不起作用:

t = TestClass.new
t.method_defined? : methodName  # => ERROR!
Run Code Online (Sandbox Code Playgroud)

所以我将它用于类和对象:

类别:

TestClass.methods.include? 'methodName'  # => TRUE
Run Code Online (Sandbox Code Playgroud)

对象:

t = TestClass.new
t.methods.include? 'methodName'  # => TRUE
Run Code Online (Sandbox Code Playgroud)

  • 对于实例,您还可以使用`instance.class.method_defined?' (3认同)

Mat*_*chu 10

" 给定一个类,看看实例是否有方法(Ruby) " 的答案更好.显然Ruby有这个内置,我不知何故错过了它.无论如何,我的答案留待参考.

Ruby类响应方法instance_methodspublic_instance_methods.在Ruby 1.8中,第一个列出了字符串数组中的所有实例方法名称,第二个将它限制为公共方法.第二种行为是您最想要的行为,因为respond_to?默认情况下也会将自身限制为公共方法.

Foo.public_instance_methods.include?('bar')
Run Code Online (Sandbox Code Playgroud)

但是,在Ruby 1.9中,这些方法返回符号数组.

Foo.public_instance_methods.include?(:bar)
Run Code Online (Sandbox Code Playgroud)

如果您计划经常这样做,您可能希望扩展Module为包含快捷方法.(分配它Module代替它可能看起来很奇怪Class,但由于这是instance_methods方法所在的位置,因此最好与该模式保持一致.)

class Module
  def instance_respond_to?(method_name)
    public_instance_methods.include?(method_name)
  end
end
Run Code Online (Sandbox Code Playgroud)

如果你想同时支持Ruby 1.8和Ruby 1.9,那么添加逻辑来搜索字符串和符号也是一个方便的地方.


imi*_*ace 5

尝试 Foo.instance_methods.include? :bar