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

时间:2010-07-21 20:04:47

标签: ruby respond-to

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

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

,比如

Foo.new.respond_to?(:bar)

但我觉得必须有一种比实例化新实例更好的方法。

12 个答案:

答案 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_methodspublic_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。