13

I have two interfaces, HasClickHandlers and DoesFancyFeedback. Then I have some UI objects that implement both interfaces - for example, a Button that implements both has click handlers and also does fancy feedback.

In my code that's declaring Buttons, I don't want to actually say Button because maybe later I'll want it to be, I don't know. An Image that has click handlers and does fancy feedback. So instead of being specific and saying something like:

Button saveButton = aButtonIPassedIn;
saveButton.addClickHandler();
saveButton.doFancyFeedback();

I want to say,

{HasClickHandlers + DoesFancyFeedback} clickyFeedbackThing = aThingIPassedIn;
clickyFeedbackThing.addClickHandler();
clickyFeedbackThing.doFancyFeedback();

I want the compiler to require that aThingIPassedIn implement both HasClickHandlers and DoesFancyFeedback.

I could create an interface that extends those two interfaces, and use that. Is there any easier/less verbose way?

2
  • You can theoretically do this with generics, I think -- place a constraint on the argument that it must implement both interfaces. However it's been a while since I've used Java generics, so my memory might be a bit tainted by .NET generics. Commented Nov 26, 2010 at 22:35
  • 1
    Any specifics (hah) on how to accomplish this would be great! Commented Nov 26, 2010 at 22:38

6 Answers 6

28

I do not think that there is a better way to do what you want. I just wanted to suggest you to do the following. You can create method (let's call it foo) that accepts argument that requires 2 interfaces:

<T extends HasClickHandlers & DoesFancyFeedback> void foo(T arg);

Please pay attention on one ampersand between 2 your interfaces.

Sign up to request clarification or add additional context in comments.

6 Comments

Whoa, who knew!? After this, it would always be safe to cast arg to either HasClickHandlers or DoesFancyFeedback, right? This would be way easier than making a composite interface for every combination of interfaces I could ever want.
@Riley: You don't have to cast it in this case, simply call the methods on it.
Just came across this question. @Riley: I guess you're talking about a method of the Display interface implemented by your view class, right? What I don't see is how you get the instance implementing HasClickHandlers and DoesFancyFeedback in your presenter code. Something like <T extends HasClickHandlers & DoesFancyFeedback> T getFancy() would be needed in the Display interface I guess. For the implementation of this method I don't see a solution without casting. Can you tell me how you'd achieved this? Thanks.
@z00bs: I ended up casting, but I added a check in the constructor to be sure that whatever object is specified is an instanceof the multiple necessary interfaces. I kept this 100% in the display code - I never pass one of these objects back to the presenter. Instead, I write exposing methods into the display, and the display does the work of casting. This keeps the complex inheritance checking in a single file. I never tried the method you suggest - seems like it would work, and I don't see why it would require casting. However, you wouldn't get errors right away w/o an explicit check.
@Riley: So you have methods like void addClickHandler(ClickHandler handler) in the Display interface you use in your presenter?
|
5

You may try to use generics:

public < T extends HashClickHandlers & DoesFancyFeedback > void foo (
        T aThingIPassedIn
    )
{
    aThingIPassedIn.addClickHandler( );
    aThingIPassedIn.doFancyFeedback( );
}

1 Comment

A great way to declare a parameter - is there any way to declare a field or other variable like this?
1

No, there is no such a thing in Java.

You would have to use the option you mention of creating a third interface. That way you'll be explicitly declaring your intention to use a new type.

Is not that verbose after all ( considering the alternative ), because you would just type:

public interface FancyWithHandler 
       extends HashClickHandlers , DoesFancyFeedback {} 

You don't need to include the methods. And then just use it:

FancyWithHandler clickyFeedbackThing = aThingIPassedIn;
clickyFeedbackThing.addClickHandler();
clickyFeedbackThing.doFancyFeedback();     

While the generic option looks interesting, probably at the end you'll end up creating a much more verbose thing.

2 Comments

OP said: "I could create an interface that extends those two interfaces, and use that. Is there any easier/less verbose way?"
I miss that part, I have changed my answer.
1

No need for a third interface nor additional method.

Optional.ofNullable((HasClickHandlers & DoesFancyFeedback)clickyFeedbackThing).ifPresent(then -> {
    then.addClickHandler();
    then.doFancyFeedback();
});

Comments

0

Although that would be ugly, you could propably make it an Object and cast it. For the calling method, it would be the easiest way.

Comments

-1

I wouldn't want a Button to implement any of those interfaces. What you're describing sounds more like the province of an event listener. Better to have the listener implement plain and fancy click handlers, and pass the listener into the Button or UI component. It's more of a delegation model that keeps processing out of the UI components and in separate classes that you can change at will.

2 Comments

You wouldn't want a Button to implement HasClickHandlers? This isn't processing, this is user interface - DoesFancyFeedback in this case is "show a twirling loading icon next to the button text," and HasClickHandlers is "tell me when the user clicks this button." After all, what would the listener you propose attach to if not the Button itself?
What is HasClickHandlers doing? Just a true/false to indicate whether something is registered?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.