Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Jython, can I make an inline anonymous class that implements a Java interface?

In Java, I can say

Thread t = new Thread(){
    public void run(){ // do stuff }
}

(or something much like that) to declare an anonymous class inline. This is most useful for making event handlers or other callback sorts of things, that in any sensible language wouldn't require an object to own them in the first place.

I face the same problem in Jython -- I want to define an event handler, but I don't want to build a whole standalone class to do so.

Ideally, I'd just be able to pass a lambda and be done with it, but if this is possible, I can't find it anywhere in the docs.

like image 303
Coderer Avatar asked Sep 14 '12 12:09

Coderer


1 Answers

Here are the background-reading links from my original answer:

Read this: Does Python have something like anonymous inner classes of Java?

Then, read this: Does Python have anonymous classes?

Finally, read this: Is it possible to create anonymous objects in Python?

[IMPROVEMENT TO ORIGINAL ANSER]

Jython implicitly converts a function to an event handler when appropriate. So, you can write this inside of one of your methods:

def _(self, event):
    print 'Cancel button was clicked!'
    if self.task is not None:
        self.task.cancel()
cancelButton.setOnAction(lambda event: _(self, event))

This approach provides three of desirable characteristics of an anonymous inner class.

(1) It is highly localized. The handler code is next to the code that assigns the handler.

(2) It is self aware, meaning you have self and can access to all of the members of the containing object.

(3) It is (almost) anonymous. Python forces me to choose a name for multi-line function, but it also allows me to reuse that name. So, I can define as many local functions called _ as long as I use them right away. (Defining a second function by the same name makes the first function inaccessible by that name.) So, I am not forced to invent unique names ad-infinitum.

You can also package this pattern in a decorator, which I think clarifies the intent a bit:

@LocalEventHandler(self, cancelButton.setOnAction)
def _(self, event):
    print 'Cancel button was clicked!'
    if self.task is not None:
        self.task.cancel()

The decorator implementation looks like this:

class LocalEventHandler(object):
    '''This decorator turns a local function into a *self aware* event handler.'''

    def __init__(self, context, assignHandlerFunc):
        self.context = context
        self.assignHandlerFunc = assignHandlerFunc

    def __call__(self, handler):
        self.assignHandlerFunc(lambda event: handler(self.context, event))
        return handler
like image 113
davidrmcharles Avatar answered Sep 20 '22 01:09

davidrmcharles