• Post Reply Bookmark Topic Watch Topic
  • New Topic

Basic Question About Interfaces  RSS feed

 
Russ Russell
Ranch Hand
Posts: 72
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

If I must provide my own implementation for the interface methods (override them), then what am I gaining by implementing the interface? Can't I simply write the functionality of the methods without implementing the interface? Will I get the same behavior?

In other words, can't I just write a public void actionPerformed(ActionEvent e) method without implementing ActionListener?

Thanks!
-Russ
 
Matthew Brown
Bartender
Posts: 4568
9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Can't I just write a public void actionPerformed(ActionEvent e) method without implementing ActionListener?


You could. But then what calls it?

If you've got something that fires events (like a button), you don't want it to have to know much about the things that are responding to those events, as that makes your application less flexible. So what is the minimum that the button needs to know about those other objects? It needs to know that they've got a method that they can call. It doesn't need to know anything about what that method does - it just needs to know that it exists.

That's where an interface comes in. We have an interface ActionListener, containing a single method actionPerformed. Any class that implements that interface is guaranteed to have an actionPerformed method. So the button can hold a list of ActionListeners and notify each one when it fires the event. It doesn't need to know any more than that.

If you've got your own class with an actionPerformed method, but that doesn't implement ActionListener, you'll find there's no way for it to be added to the list the button holds.


More generally, an interface allows you to separate what an object can do from how it does it. And that separation gives you a lot of flexibility because as long as you're referencing the interface you can switch between different implementations of the interface without anything else being affected. In this example, different classes implementing ActionListener are interchangeable. This is polymorphism - treating a bunch of objects the same way even though the implementation details might be completely different.

Does that help?
 
Russ Russell
Ranch Hand
Posts: 72
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Matthew, thanks for the reply. I'm not sure I understand your answer though.

Are you saying that in order to call button.addActionListener(new Listener()), class Listener itself has to implement (be an) ActionListener?

What I don't get is that if the method ActionPerformed(ActionEvent e) is completely un-defined in the ActionListener class , and I must be the one to define it, why can't I just define it without the need for the "contract" with the ActionListener class? What is the ActionListener class bringing to the table except an empty method that I must define anyway?

Thanks again, and sorry for the newbie nature of this question.
-Russ
 
Matthew Brown
Bartender
Posts: 4568
9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Think about how you could define the method in button that lets you added listeners:
Using this approach, you can only add listeners that implement ActionListener. Which means the compiler can guarantee that they have an actionPerformed() method. The button can happily call this method without any danger whatsover.

This would let you add anything as a listener. But then there's no guarantee what methods it has. The button would have to do some nasty reflection to find out if each object has an actionPerformed() method. And what is it going to do if it doesn't? It can't do anything, which means that adding the listener was a mistake. As a rule, it's much better to let the compiler find errors whenever possible, but the compiler can't help you here.

Here it's referencing your object, which you know has an actionPerformed() method. But that means the button had to know that your class would exist before you wrote it. So that's no good.

Any other suggestions?

You'll find the only satisfactory method signature is the one that defines the contract the listener needs to support, and nothing else. That's exactly what an interface does.
 
fred rosenberger
lowercase baba
Bartender
Posts: 12563
49
Chrome Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
when a user presses a button on your gui, some method needs to be called. The folks who wrote the code for the button have NO idea what your class and/or method will be called. How could they, since they wrote their side years ago?

So, they defined a contract. They said "When a user presses the button, we will call the actionPerformed method on whatever object is attached to the button. We don't care what the method does, but we will call it."

without the contract, you might write a "myActionPerformed" method, or an "Action" method, or who knows what...

By defining the interface, and hence the contract, it doesn't matter that you are coming along years later - the rules are already defined.

 
Russ Russell
Ranch Hand
Posts: 72
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Fred. I'm starting to get it. Here's what I don't understand:

If addActionListener() simply required an object as an input paramater instead of requiring a spefic type of object (an ActionListener), then I sould be able to do the following, right?:







 
fred rosenberger
lowercase baba
Bartender
Posts: 12563
49
Chrome Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
But addActionListener does NOT require a specific type of object. you can stick in ANY type of object, as long as it implements the ActionListener interface.

and your comment:

//I promise to implement actionPerformed in my class!

by using interfaces, the compiler can enforce that you really do. By saying "implements ActionListener", you are effectively telling the compiler "i promise to implement the ActionPerformed in my class" in such a way that it knows what you are promising, and forces you to do so.
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Russ Russell wrote:Thanks Fred. I'm starting to get it. Here's what I don't understand:

If addActionListener() simply required an object as an input paramater instead of requiring a spefic type of object (an ActionListener), then I sould be able to do the following, right?:


Yes, but if it accepted a plain ol' Object, then the compiler wouldn't be able to guarantee that the actionPerformed() method would be present for the Swing framework to call, since Object doesn't define that method.
 
Russ Russell
Ranch Hand
Posts: 72
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
But my object does define that method. I guess the compiler couldn't check every method of the object to ensure it has an actionPerformed() method.
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Russ Russell wrote:But my object does define that method. I guess the compiler couldn't check every method of the object to ensure it has an actionPerformed() method.


In this specific case, it could, but that's not how it works. The compiler just looks at the declared type. If it's declare as Object, then as far as the compiler knows, it has only Object's methods. If it's declared as ActionListener, then the compiler knows it has ActionListener's methods.

Let's take a simple counterexample:



We cannot pass that Object to addActionListener()*.

The compiler knows that the declared type of the expression on the RHS of the = sign is Object, because we're calling a method that declares it returns Object. The compiler does not look into the body of the method to see what object will actually be returned at runtime. In the general case, it is simply not possible. So rather than some half-arsed, overly complex, sometimes yes, sometimes no confusion, the rules are simply that the compiler looks at the declared type, and by that type, it can guarantee what methods will be present.

* Okay, so would could pass it if we were to cast it. But that's a topic for another discussion.
 
Russ Russell
Ranch Hand
Posts: 72
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you for helping me understand the "why" of it. That helps to make it clear in my mind.

So in summary, If the compiler sees an ActionListener as the paramter for addActionListener(), it knows that all is well, and an actionPerformed() will be defined. This is the simpest way that the compiler can ensure actionPerformed() will exist for the button. Is this correct?
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Russ Russell wrote:Thank you for helping me understand the "why" of it. That helps to make it clear in my mind.

So in summary, If the compiler sees an ActionListener as the paramter for addActionListener(), it knows that all is well, and an actionPerformed() will be defined. This is the simpest way that the compiler can ensure actionPerformed() will exist for the button. Is this correct?


Yup. That pretty much sums it up. I'm sure a language designer or compiler writer could go into more technical detail, but for a user of the language, that should cover it.

Although, just to nitpick a bit, and hopefully not muddy the waters in the process: At the point where you're passing a parameter to addActionListener(), the compiler doesn't care about the actionPerformed() method. All it cares about is that addActionListener requires an ActionListener param. As a separate, independent step from that, the compiler looks at the thing that you're calling an ActionListener--that is, that your declaring to implement that interface--to make sure that it actually defines all the methods required of an ActionListener.

 
fred rosenberger
lowercase baba
Bartender
Posts: 12563
49
Chrome Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Russ Russell wrote:But my object does define that method. I guess the compiler couldn't check every method of the object to ensure it has an actionPerformed() method.

Also, remember that you can compile your class in a vacuum. When it is compiled, it isn't attached to anything - it's just in a file all by itself (potentially). The compiler COULD check every class, but since 99% of them don't need this method, it would be a huge waste. And then you'd be writing this board saying "Why does my HelloWorld class need an 'actionPerformed' method?"
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!