48

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
  • 36,743
  • 36
  • 104
  • 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

76

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
  • 185,044
  • 174
  • 569
  • 824
6

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,799
  • 3
  • 22
  • 31
marcospereira
  • 12,045
  • 3
  • 46
  • 52
  • 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,189
  • 7
  • 38
  • 45
4

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,968
  • 2
  • 31
  • 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
  • 87,526
  • 38
  • 249
  • 254
-1

In very concise way you can use this:

if(someObj.&methodName){
 //it means someObj has the method
}
dsharew
  • 10,377
  • 6
  • 49
  • 75
  • I wish it worked ! `someObj.&methodName` always returns a closure, even if no method with given name exists. This must be due to runtime resolution of the method with calling arguments. Cf. https://docs.groovy-lang.org/latest/html/documentation/core-operators.html#method-pointer-operator – Ludovic Ronsin Jul 07 '22 at 15:58