Note: in this question, I am talking about formal Interfaces (e.g. public interface IButton {...} ).
I'm an Actionscript developer, but I suspect my question will resonate in many languages that allow both formal Interfaces and Events.
I love Interfaces. I love the separation between interface and implementation. (I wish Actionscript forced every class to implement a formal Interface, the way Objective-C does.) All of my classes implement an interface (or several), and you'll never find me writing a public method than isn't referenced in an Interface.
But Actionscript is also heavily dependent on Events. My problem is this: every part of a class that communicates with external classes or processes is (or should be) part of its Interface. (I realize this is a matter of opinion. If you disagree, this question will probably be meaningless to you.)
There are several ways to muddy this clear picture, but most of them are avoidable:
You can't list public properties in an Interface. Solution: don't use public properties in your classes. Use getters and setters instead (and I'm not all that crazy about them, either, but I use them when I must).
If classes communicate by passing arguments to constructors, those messages bypass Interfaces, since you can't list a constructor function in an Interface. I avoid this problem by (almost) never passing parameters through constructors. I prefer init() methods that can be made explicit in Interfaces.
Classes can have public methods that aren't listed in an Interface. I avoid this by not doing it. My classes implement Interfaces. Those Interfaces contain headers for ALL public methods.
Many classes dispatch Events.
That last one is the killer.
Let's say I give you a class called Blah, and you ask me how to use it. I can tell you, "It implements the IBlah Interface. Just look at that and you'll see everything you can do with Blah."
Except Blah extends EventDispatcher, which implies that it dispatches Events.
"What Events does it dispatch?" You ask.
"Uh..."
To know, you have to check the JavaDoc or read through Blah's source code. You shouldn't have to do either! You should be able to know how to interact with a class by checking its Interface(s).
I wish Interfaces could look like this:
public interface IBlah
{
function foo() : void;
function bar() : Boolean;
event BlahEvent;
}
But you can't specify events in an Interface.
Am I right that Events break Interfaces? To me, it's as if I gave you a car and said here's the manual. In the manual, it supposedly explains everything that's on the dashboard. But then, when you're driving the car, weird dohickies appear and strange sounds play -- Events that aren't mentioned in the manual.
If I'm wrong, please explain.
If I'm right, is there a good way to avoid the problem?