Dada una clase, ver si la instancia tiene método (Ruby)
Sé en Ruby que puedo usar respond_to?
para comprobar si un objeto tiene cierto método.
Pero, dada la clase, ¿cómo puedo comprobar si la instancia tiene un cierto método?
Es decir, algo como
Foo.new.respond_to?(:bar)
Pero siento que tiene que haber una mejor manera que instanciar una nueva instancia.
10 answers
No se porque todo el mundo esta sugiriendo que deberías usar instance_methods
y include?
cuando method_defined?
hace el trabajo.
class Test
def hello; end
end
Test.method_defined? :hello #=> true
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-09 14:56:46
Puedes usar method_defined?
de la siguiente manera:
String.method_defined? :upcase # => true
Mucho más fácil, portátil y eficiente que el instance_methods.include?
todo el mundo parece estar sugiriendo.
Tenga en cuenta que no sabrá si una clase responde dinámicamente a algunas llamadas con method_missing
, por ejemplo redefiniendo respond_to?
, o desde Ruby 1.9.2 definiendo respond_to_missing?
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-21 23:27:22
En realidad esto no funciona tanto para Objetos como para Clases.
Esto hace:
class TestClass
def methodName
end
end
Así que con la respuesta dada, esto funciona:
TestClass.method_defined? :methodName # => TRUE
Pero esto NO funciona:
t = TestClass.new
t.method_defined? : methodName # => ERROR!
Así que uso esto tanto para clases como para objetos:
Clases:
TestClass.methods.include? 'methodName' # => TRUE
Objetos:
t = TestClass.new
t.methods.include? 'methodName' # => TRUE
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-10 20:34:38
La respuesta a " Dada una clase, ver si la instancia tiene método (Ruby)" es mejor. Aparentemente Ruby tiene esto incorporado, y de alguna manera me lo perdí. Mi respuesta se deja como referencia, a pesar de todo.
Ruby clases responder a los métodos instance_methods
y public_instance_methods
. En Ruby 1.8, la primera lista todos los nombres de métodos de instancia en una matriz de cadenas, y la segunda lo restringe a métodos públicos. El segundo comportamiento es lo que probablemente querrías, ya que respond_to?
se restringe a sí mismo a los métodos públicos por defecto, también.
Foo.public_instance_methods.include?('bar')
En Ruby 1.9, sin embargo, esos métodos devuelven matrices de símbolos.
Foo.public_instance_methods.include?(:bar)
Si está planeando hacer esto a menudo, es posible que desee extender Module
para incluir un método abreviado. (Puede parecer extraño asignar esto a Module
en lugar de Class
, pero ya que es donde viven los métodos instance_methods
, es mejor mantenerse en línea con ese patrón.)
class Module
def instance_respond_to?(method_name)
public_instance_methods.include?(method_name)
end
end
Si desea soportar Ruby 1.8 y Ruby 1.9, ese sería un lugar conveniente para agregar la lógica para buscar tanto cadenas como símbolos.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:50
No estoy seguro de si esta es la mejor manera, pero siempre puedes hacer esto:
Foo.instance_methods.include? 'bar'
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-21 20:10:23
Creo que hay algo malo con method_defined?
en Rails. Puede ser inconsistente o algo así, por lo que si usa Rails, es mejor usar algo de attribute_method?(attribute)
.
"testing for method_defined? en ActiveRecord las clases no funcionan hasta que una instanciación " es una pregunta sobre la inconsistencia.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:41
Si está comprobando si un objeto puede responder a una serie de métodos, podría hacer algo como:
methods = [:valid?, :chase, :test]
def has_methods?(something, methods)
methods & something.methods == methods
end
El methods & something.methods
unirá los dos arrays en sus elementos comunes/coincidentes. algo.methods incluye todos los métodos que está comprobando, igualará los métodos. Por ejemplo:
[1,2] & [1,2,3,4,5]
==> [1,2]
So
[1,2] & [1,2,3,4,5] == [1,2]
==> true
En esta situación, querrás usar símbolos, porque cuando llamas .métodos, devuelve una matriz de símbolos y si se utiliza ["my", "methods"]
, devolvería false.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-06 21:41:28
Intenta Foo.instance_methods.include? :bar
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-06 21:50:40
klass.instance_methods.include :method_name
o "method_name"
, dependiendo de la versión de Ruby creo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-09 00:49:37
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]
¡Espero que esto te ayude!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-09 00:50:40