45

Assuming that I have an object someObj of indeterminate type, I'd like to do something like:

def value = someObj.someMethod()

Where there's no guarantee that 'someObj' implements the someMethod() method, and if it doesn't, just return null.

Is there anything like that in Groovy, or do I need to wrap that in an if-statement with an instanceof check?

Electrons_Ahoy
  • 33,803
  • 35
  • 102
  • 127
  • One way would be to interate `.properties` per http://stackoverflow.com/questions/2585992/how-to-get-all-property-names-of-a-groovy-class – MarkHu Feb 04 '16 at 05:31

6 Answers6

72

Use respondsTo

class Foo {
   String prop
   def bar() { "bar" }
   def bar(String name) { "bar $name" }
}

def f = new Foo()

// Does f have a no-arg bar method
if (f.metaClass.respondsTo(f, "bar")) {
   // do stuff
}
// Does f have a bar method that takes a String param
if (f.metaClass.respondsTo(f, "bar", String)) {
   // do stuff
}
Dónal
  • 181,534
  • 169
  • 555
  • 808
5

Just implement methodMissing in your class:

class Foo {
   def methodMissing(String name, args) { return null; }
}

And then, every time you try to invoke a method that doesn't exist, you will get a null value.

def foo = new Foo();
assert foo.someMethod(), null

For more information, take a look here: http://groovy.codehaus.org/Using+methodMissing+and+propertyMissing

Jörgen Lundberg
  • 1,749
  • 3
  • 22
  • 31
marcospereira
  • 11,845
  • 3
  • 46
  • 51
  • That means all his Objects that don't have the someMethod behavior would have to implement the method? – Langali Oct 07 '09 at 21:37
4

You should be able to do something like:

SomeObj.metaClass.getMetaMethod("someMethod")

Or you can fall back to the good old Java reflection API.

Langali
  • 3,119
  • 7
  • 36
  • 45
3

You can achieve this by using getMetaMethod together with the safe navigation operator ?.:

def str = "foo"
def num = 42

def methodName = "length"
def args = [] as Object[]

assert 3 == str.metaClass.getMetaMethod(methodName, args)?.invoke(str, args);
assert null == num.metaClass.getMetaMethod(methodName, args)?.invoke(num, args);
Christoph Metzendorf
  • 7,848
  • 2
  • 29
  • 28
2

if class :

   MyClass.metaClass.methods*.name.any{it=='myMethod'}//true if exist

if object :

myObj.class.metaClass.methods*.name.any{it=='myMethod'}//true if exist
Abdennour TOUMI
  • 76,783
  • 33
  • 229
  • 231
-1

In very concise way you can use this:

if(someObj.&methodName){
 //it means someObj has the method
}
dsharew
  • 9,927
  • 6
  • 43
  • 71