Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a Groovy closure extend an abstract class

I have an abstract Java class that needs to have one method onMessage to be implemented. I know that a closure can easily implement a Java interface using the as keyword, but how can it extend an abstract Java class?

If it can't extend it, then whats the best work around possible in such cases in Groovy?

Here is my usage in Java, I am looking for something similar that can be done in Groovy.

MessageCallback callback = new MessageCallback() {
            @Override
            public void onMessage(Message message) {
                dosomething();
            }
        };

Where message callback is my abstract class which I would like to use in a similar fashion in Groovy.

like image 953
Abe Avatar asked Aug 17 '11 11:08

Abe


People also ask

Can abstract class be extended?

In Java, abstract means that the class can still be extended by other classes but that it can never be instantiated (turned into an object).

How do you extend an abstract method?

To declare an abstract method, use this general form: abstract type method-name(parameter-list); As you can see, no method body is present. Any concrete class(i.e. class without abstract keyword) that extends an abstract class must override all the abstract methods of the class.

Can an abstract class extend a final method?

therefore, a final abstract combination is illegal for classes. Hence, a final class cannot contain abstract methods whereas an abstract class can contain a final method.

Can interface extend multiple abstract class?

Interfaces cannot have instance variables and method implementations(except default methods) which is not the case for abstract classes. A class can implement multiple interfaces but can only extend one class regardless of abstraction.


3 Answers

I believe you should be able to do:

def callback = [ onMessage:{ message -> doSomething() } ] as MessageCallback

Does that not work?

Edit

To make a call from the Map method back to the Abstract class, the only way I can find to do it is:

// Dummy class for testing
abstract class MessageTest {
  abstract void onMessage( msg ) ;
  void done() { println "DONE!" }
}

// Create a Proxied instance of our class, with an empty onMessage method
def p = [ onMessage:{ msg -> } ] as MessageTest

// Then overwrite the method once we have access to the Proxy object p
p.metaClass.onMessage = { msg -> println msg ; p.done() }

// Test
p.onMessage( 'woo' )
like image 126
tim_yates Avatar answered Sep 18 '22 23:09

tim_yates


Yo can do this:

Implements a method in any class:

public MessageTest messageTest(Closure callback) {
    return new MessageTest() {
        @Override
        public void onMessage(Message message) {
            callback.call(message)
        }
    }
}

In main class in main method:

def outerMessage

MessageTest messageTest = messageTest() {message ->
    outerMessage = message
    println "innerMessage: $message"
}

messageTest.onMessage("This is the message...")
println "outerMessage: $outerMessage"

Your output should show this:

innerMessage: This is the message...
outerMessage: This is the message...
like image 43
Sergio Valdez Avatar answered Sep 19 '22 23:09

Sergio Valdez


Basing on @tim_yates, here is a version of method which creates object of an abstract class from a closure. I needed something like that to be able instantiate such object in just one line.

// Dummy class for testing
abstract class MessageTest {
  abstract void onMessage( msg ) ;
  void done() { println "DONE!" }
}

MessageTest createMessageTest(Closure closure) {
  // Create a Proxied instance of our class, with an empty onMessage method
  def p = [ onMessage:{ msg -> } ] as MessageTest

  // Then overwrite the method once we have access to the Proxy object p
  p.metaClass.onMessage = closure
  return p
}

// Create
MessageTest mt = createMessageTest { msg -> 
  println msg ; 
  done() 
}

// Test
mt.onMessage( 'woo' )
like image 36
kokosing Avatar answered Sep 19 '22 23:09

kokosing