242

Rubyrespond_to?では、オブジェクトに特定のメソッドがあるかどうかを確認するために使用できることを知っています。

しかし、クラスが与えられた場合、インスタンスに特定のメソッドがあるかどうかを確認するにはどうすればよいですか?

つまり、

Foo.new.respond_to?(:bar)

しかし、新しいインスタンスをインスタンス化するよりも良い方法があると思います。

4

12 に答える 12

379

instance_methods誰もがあなたが使うべきだと提案している理由と、include?いつ仕事をするのかわかりませんmethod_defined?

class Test
  def hello; end
end

Test.method_defined? :hello #=> true

ノート

別の 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 型の文字列) の両方であるためです。

于 2010-07-21T23:28:35.717 に答える
45

method_defined?次のように使用できます。

String.method_defined? :upcase # => true

instance_methods.include?他の人が提案しているように見えるよりもはるかに簡単で、移植性があり、効率的です。

method_missingクラスが、たとえば を再定義respond_to?することによって、または Ruby 1.9.2 以降では を定義することによって、いくつかの呼び出しに動的に応答するかどうかはわからないことに注意してrespond_to_missing?ください。

于 2010-07-21T23:27:22.153 に答える
10

「クラスが与えられた場合、インスタンスにメソッド(Ruby)があるかどうかを確認してください」に対する答えの方が優れています。どうやらRubyにはこれが組み込まれているようで、どういうわけか見逃していました。とにかく、私の答えは参照用に残されています。

instance_methodsRuby クラスはメソッドおよびに応答しますpublic_instance_methods。Ruby 1.8 では、1 つ目はすべてのインスタンス メソッド名を文字列の配列にリストし、2 つ目はそれをパブリック メソッドに制限します。respond_to?2 番目の動作は、デフォルトでパブリック メソッドにも制限されているため、最も望ましい動作です。

Foo.public_instance_methods.include?('bar')

しかし、Ruby 1.9 では、これらのメソッドはシンボルの配列を返します。

Foo.public_instance_methods.include?(:bar)

これを頻繁に行うことを計画している場合Moduleは、ショートカット メソッドを含めるように拡張することをお勧めします。Module( this をの代わりにに割り当てるのは奇妙に思えるかもしれません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 の両方をサポートする場合は、文字列とシンボルの両方を検索するロジックを追加するのに便利な場所です。

于 2010-07-21T20:09:32.193 に答える
5

試すFoo.instance_methods.include? :bar

于 2010-07-21T20:11:38.557 に答える
3

これが最善の方法かどうかはわかりませんが、いつでもこれを行うことができます:

Foo.instance_methods.include? 'bar'
于 2010-07-21T20:10:23.393 に答える
3

オブジェクトが一連のメソッドに応答できるかどうかを確認する場合は、次のようにすることができます。

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

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

これmethods & something.methodsは、共通/一致する要素で2つの配列を結合します。something.methods には、チェックしているすべてのメソッドが含まれます。メソッドと同じになります。例えば:

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

それで

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

この状況では、.methods を呼び出すとシンボルの配列が返され、.methods を使用すると["my", "methods"]false が返されるため、シンボルを使用する必要があります。

于 2014-01-27T11:29:04.977 に答える
2

klass.instance_methods.include :method_nameまたは"method_name"、私が考えるRubyのバージョンによって異なります。

于 2010-07-21T20:09:40.353 に答える