views:

96

answers:

5

This may be a fairly subjective question, but maybe not. My application contains a bunch of forms that are displayed to the user at different times. Each form is a class of its own. Typically the user clicks a button, which launches a new form.

I have a convenience function that builds these buttons, you call it like this:

buildButton( "button text", new SelectionAdapter() {
     @Override
     public void widgetSelected( SelectionEvent e ) {
        showForm( new TasksForm( args... ) );
     }
  } );

I do this dozens of times, and it's really cumbersome having to make a SelectionAdapter every time.

Really all I need for the button to know is what class to instantiate when it's clicked and what arguments to give the constructor, so I built a function that I call like this instead:

buildButton( "button text", TasksForm.class, args... );

Where args is an arbitrary list of objects that you could use to instantiate TasksForm normally.

It uses reflection to get a constructor from the class, match the argument list, and build an instance when it needs to. Most of the time I don't have to pass any arguments to the constructor at all. The downside is obviously that if I'm passing a bad set of arguments, it can't detect that at compilation time, so if it fails, a dialog is displayed at runtime. But it won't normally fail, and it'll be easy to debug if it does.

I think this is much cleaner because I come from languages where the use of function and class literals is pretty common. But if you're a normal Java programmer, would seeing this freak you out, or would you appreciate not having to scan a zillion SelectionAdapters?

+3  A: 

Yeah, usually reflection is frowned upon but in some cases it can be quite useful. I would appreciate reading code which i can digest fairly quickly without having to go through a zillion little thingies.

JHollanti
A: 

The problem is not reflection per se. Modern frameworks use reflection all the time. And it's hip to use annotations to do all sorts of things, which usually requires reflection.

However, in your case, why dont you just do:

buildButton( "button text",
        new SelectionAdapterImplementation(new TaskForm(args)) )

unless your anonymous class is using final variables from the scope, I see no reason.

Artefacto
If I understand you correctly, you're suggesting not using anonymous classes, in which case I'd have to build an implementation of SelectionAdapter for every class I wanted to instantiate. Unfortunately, I have dozens of them (TasksForm was just an example.) Seems even more cluttered to me, but maybe I'm misunderstanding.
jsn
Ok, you're right. Go with reflection then, or pass the TaskForm object instead.
Artefacto
I've edited the post accordingly.
Artefacto
A: 

You have modified your buildButton(String, SelectionAdapter) to take a class on which you will reflect. I gather that you now are creating a new SelectionAdapter in your modified method and then reflecting on the class name, creating an instance and passing that into showForm(arg). I think this is a step farther than you need to go.

Instead, you can have it take an instance of whatever class your showForm(arg) requires. The key will be to make that arguement final in your arglist for buildButton, and you will be able to use it in your anonymous class.

akf
Because the form is a user interface component, I can't instantiate it when I build the button, I have to wait until the button is clicked, hence the SelectionAdapter
jsn
A: 

One alternative way is to have a static method in each form that returns a button that creates the form. But reflection would probably be better.

tulskiy
+1  A: 

If I understand correctly, you want to execute one operation (createButton) with different kinds of button implementations (forms) for argument. This sounds exactly like you need polymorphism.

I suggest you forget about reflection and construct these forms under a common interface. Let's say interface Form { //some methods here }

All your forms will have to implement the common interface and these methods are required for the creation of the button. So if you have a Form object, you can pass it to the createButton(Form formObject){...}

IF all SelectionAdapter does is call a showForm method, you can add it to the common interface Form and just invoke this method for a Form object. Thus you don't need to create many anonymous classes but just one and instantiating it with a "Form" object.

So all you need is polymorphism and nicely chosen interfaces for these classes.

If you have a big problem with creating the Form objects (their constructors differ), may be you should consider creating a MyFormBuilder which handles construction only. The builder will have createInstance() method or getInstance() method which will do all the work.

With my suggestion you will have 1 SelectionAdapter class implementation, you will be passing objects with common interface and will have avoided reflection, passing MyClass.class arguments and so on.

Leni Kirilov