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

发布于 2024-09-10 16:46:06 字数 189 浏览 6 评论 0 原文

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

但是,给定类,我如何检查实例是否具有某种方法?

即,类似

Foo.new.respond_to?(:bar)

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

I know in Ruby that I can use respond_to? to check if an object has a certain method.

But, given the class, how can I check if the instance has a certain method?

i.e, something like

Foo.new.respond_to?(:bar)

But I feel like there's gotta be a better way than instantiating a new instance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

苹果你个爱泡泡 2024-09-17 16:46:06

我不知道为什么每个人都建议当 method_define? 完成这项工作时,您应该使用 instance_methodsinclude?

class Test
  def hello; end
end

Test.method_defined? :hello #=> true

注意

如果您从另一种面向对象语言转向 Ruby,或者您认为 method_define 只表示您显式定义的方法:

def my_method
end

那么请阅读以下内容:

在 Ruby 中,属性 (模型上的属性)基本上也是一种方法。因此,method_define? 也将为属性返回 true,不仅仅是方法。

例如:

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

<instance>.first_name.class #=> String

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

因为 first_name 既是属性又是方法(以及 String 类型的字符串)。

I don't know why everyone is suggesting you should be using instance_methods and include? when method_defined? does the job.

class Test
  def hello; end
end

Test.method_defined? :hello #=> true

NOTE

In case you are coming to Ruby from another OO language OR you think that method_defined means ONLY methods that you defined explicitly with:

def my_method
end

then read this:

In Ruby, a property (attribute) on your model is basically a method also. So method_defined? will also return true for properties, not just methods.

For example:

Given an instance of a class that has a String attribute first_name:

<instance>.first_name.class #=> String

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

since first_name is both an attribute and a method (and a string of type String).

℡寂寞咖啡 2024-09-17 16:46:06

您可以按如下方式使用 method_define?

String.method_defined? :upcase # => true

比其他人似乎都建议的 instance_methods.include? 更容易、可移植且高效。

请记住,您不会知道类是否通过 method_missing 动态响应某些调用,例如通过重新定义 respond_to?,或者从 Ruby 1.9.2 开始通过定义 < a href="http://github.com/ruby/ruby/blob/trunk/vm_method.c#L1288" rel="noreferrer">respond_to_missing?

You can use method_defined? as follows:

String.method_defined? :upcase # => true

Much easier, portable and efficient than the instance_methods.include? everyone else seems to be suggesting.

Keep in mind that you won't know if a class responds dynamically to some calls with method_missing, for example by redefining respond_to?, or since Ruby 1.9.2 by defining respond_to_missing?.

夜无邪 2024-09-17 16:46:06

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

确实如此:

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

Actually this doesn't work for both Objects and Classes.

This does:

class TestClass
  def methodName
  end
end

So with the given answer, this works:

TestClass.method_defined? :methodName # => TRUE

But this does NOT work:

t = TestClass.new
t.method_defined? : methodName  # => ERROR!

So I use this for both classes and objects:

Classes:

TestClass.methods.include? 'methodName'  # => TRUE

Objects:

t = TestClass.new
t.methods.include? 'methodName'  # => TRUE
吃不饱 2024-09-17 16:46:06

给出一个类,看看是否实例有方法 (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,那么这也是添加搜索字符串和符号的逻辑的方便位置。

The answer to "Given a class, see if instance has method (Ruby)" is better. Apparently Ruby has this built-in, and I somehow missed it. My answer is left for reference, regardless.

Ruby classes respond to the methods instance_methods and public_instance_methods. In Ruby 1.8, the first lists all instance method names in an array of strings, and the second restricts it to public methods. The second behavior is what you'd most likely want, since respond_to? restricts itself to public methods by default, as well.

Foo.public_instance_methods.include?('bar')

In Ruby 1.9, though, those methods return arrays of symbols.

Foo.public_instance_methods.include?(:bar)

If you're planning on doing this often, you might want to extend Module to include a shortcut method. (It may seem odd to assign this to Module instead of Class, but since that's where the instance_methods methods live, it's best to keep in line with that pattern.)

class Module
  def instance_respond_to?(method_name)
    public_instance_methods.include?(method_name)
  end
end

If you want to support both Ruby 1.8 and Ruby 1.9, that would be a convenient place to add the logic to search for both strings and symbols, as well.

一口甜 2024-09-17 16:46:06

尝试 Foo.instance_methods.include 吗? :栏

Try Foo.instance_methods.include? :bar

七颜 2024-09-17 16:46:06

不确定这是否是最好的方法,但您始终可以这样做:

Foo.instance_methods.include? 'bar'

Not sure if this is the best way, but you could always do this:

Foo.instance_methods.include? 'bar'
っ左 2024-09-17 16:46:06

我认为 Rails 中的 method_define? 有问题。它可能不一致或其他什么,所以如果你使用 Rails,最好使用 attribute_method?(属性)

在 ActiveRecord 类上测试 method_define?在实例化之前不起作用”是关于不一致的问题。

I think there is something wrong with method_defined? in Rails. It may be inconsistent or something, so if you use Rails, it's better to use something from attribute_method?(attribute).

"testing for method_defined? on ActiveRecord classes doesn't work until an instantiation" is a question about the inconsistency.

隐诗 2024-09-17 16:46:06

如果您要检查一个对象是否可以响应一系列方法,您可以执行以下操作:

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

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

methods & some.methods 将在两个数组的公共/匹配元素上连接它们。 some.methods 包括您正在检查的所有方法,它等于方法。例如:

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

所以

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

在这种情况下,您需要使用符号,因为当您调用 .methods 时,它会返回符号数组,并且如果您使用 ["my", "methods"],它会返回 false。

If you're checking to see if an object can respond to a series of methods, you could do something like:

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

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

the methods & something.methods will join the two arrays on their common/matching elements. something.methods includes all of the methods you're checking for, it'll equal methods. For example:

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

so

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

In this situation, you'd want to use symbols, because when you call .methods, it returns an array of symbols and if you used ["my", "methods"], it'd return false.

我的鱼塘能养鲲 2024-09-17 16:46:06
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] 

希望这对您有帮助!

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] 

Hope this helps you!

書生途 2024-09-17 16:46:06

klass.instance_methods.include :method_name"method_name",具体取决于我认为的 Ruby 版本。

klass.instance_methods.include :method_name or "method_name", depending on the Ruby version I think.

无风消散 2024-09-17 16:46:06

虽然 respond_to? 仅对公共方法返回 true,但检查类上的“方法定义”也可能与私有方法有关。

在 Ruby v2.0+ 上,可以通过以下方式检查公共集和私有集:

Foo.private_instance_methods.include?(:bar) || Foo.instance_methods.include?(:bar)

While respond_to? will return true only for public methods, checking for "method definition" on a class may also pertain to private methods.

On Ruby v2.0+ checking both public and private sets can be achieved with

Foo.private_instance_methods.include?(:bar) || Foo.instance_methods.include?(:bar)
-残月青衣踏尘吟 2024-09-17 16:46:06

在我使用 ruby​​ 2.5.3 的情况下,以下句子完美运行:

value = "hello world"

value.methods.include? :upcase

它将返回布尔值 true 或 false。

On my case working with ruby 2.5.3 the following sentences have worked perfectly :

value = "hello world"

value.methods.include? :upcase

It will return a boolean value true or false.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文