Actually, it's the other way around. Authors make methods final not because *you* might make a mistake but rather because *they* might. Using final methods simplifies their design a lot because they don't have to do all the work you mentioned. Secondly, it leaves the API open to extension (without breaking backwards compatibility) in a way that would be lost if anyone could override the methods.
I personally agree with your approach with the following major caveat: if developers are able to override any method then it must be understood that any implementation making assumptions not guaranteed by the API specification is liable to break in future releases. Keep in mind that very few things ever are guaranteed by the specification, so practically speaking this means that your code is very likely to break as new releases come out. To be honest, I personally prefer approach #2 over final methods for public projects because (in my experience) even open-source projects take forever to fix bugs or add features that you might need right away. I'm a strong believer that implementations that make incorrect assumptions deserve to break in subsequent releases. One final benefit of #1 worth mentioning, however, is that incorrect assumptions end up in a compile-time error (roughly speaking) and even smart developers make mistakes every once in a while. Consider what happens if you override foo() and forget to invoke super.foo() by mistake. Those kinds of mistakes happen all the time. I'm toying with the idea that approach #1 makes sense for in-house projects where you are a co-owner and can make changes very quickly while approach #2 makes sense for public projects when developers can't afford to wait on the project owner. Put another way, maybe #1 makes sense for mature APIs whereas #2 makes sense for experimental APIs (used to flesh out the various use-cases you need to support). Gili Brill Pappin wrote: > > I understand the reasoning, however I think "best practice" can be > debated. > To use your example Swing allows the user to override quite a bit, and > it doesn't make any (or very few) assumptions on what should and > should not be done. > > I don't like API's that assume I'm an idiot and prevent me from > manipulating them how I see fit. If I cause a bug that I have to deal > with, thats *my* problem to resolve. > > In my book (and I'm not the only one) excessive use of final is an > anti-pattern. > > - Brill Pappin > > On 12-Jun-08, at 10:01 AM, cowwoc wrote: > >> >> Brill, >> >> This is actually an API "best practice". Classes fall into two >> categories: >> ones designed for subclassing, and ones designed to be final. The >> same goes >> for methods. Swing is full of examples of what goes wrong when people >> override methods in classes that haven't been designed with >> subclassing in >> mind. >> >> Gili >> >> >> Brill Pappin wrote: >>> >>> on removing the finals >>> >>> The final members are the worst thing I've had to deal with in Wicket >>> so far. >>> Although I understand that there may be a reason for them, they are >>> more a hinderance than anything else and seem to be trying to >>> "protect >>> users from themselves". >>> >>> - Brill Pappin >>> >>> >>> On 12-Jun-08, at 1:03 AM, cowwoc wrote: >>> >>>> >>>> >>>> Have you considered moving from subclassing to composition in Wicket >>>> using >>>> Callable<T>? >>>> >>>> Currently it is quite common for developers to subclass a component >>>> in order >>>> to override isVisible() and other properties. I am proposing that >>>> instead >>>> the component classes become final and properties may only be set >>>> using >>>> setter methods. The setter methods would take Callable<T> instead of >>>> T, so >>>> for example setVisible(boolean) would become >>>> setVisible(Callable<Boolean>) >>>> >>>> The benefit of this approach is that you could introduce static >>>> factory >>>> methods to the Wicket components which would make them much easier >>>> to use in >>>> their Generic form. You could then introduce various helper >>>> classes to >>>> create Callable<T> for constant values, such as >>>> Callable.valueOf(true) would >>>> return a Callable<Boolean> that always returns true. >>>> -- >>>> View this message in context: >>>> http://www.nabble.com/users%2C-please-give-us-your-opinion%3A-what-is-your-take-on-generics-with-Wicket-tp17589984p17792488.html >>>> Sent from the Wicket - User mailing list archive at Nabble.com. >>>> >>>> >>>> --------------------------------------------------------------------- >>>> To unsubscribe, e-mail: [EMAIL PROTECTED] >>>> For additional commands, e-mail: [EMAIL PROTECTED] >>>> >>> >>> >>> --------------------------------------------------------------------- >>> To unsubscribe, e-mail: [EMAIL PROTECTED] >>> For additional commands, e-mail: [EMAIL PROTECTED] >>> >>> >>> >> >> -- >> View this message in context: >> http://www.nabble.com/users%2C-please-give-us-your-opinion%3A-what-is-your-take-on-generics-with-Wicket-tp17589984p17800710.html >> Sent from the Wicket - User mailing list archive at Nabble.com. >> >> >> --------------------------------------------------------------------- >> To unsubscribe, e-mail: [EMAIL PROTECTED] >> For additional commands, e-mail: [EMAIL PROTECTED] >> > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > > > -- View this message in context: http://www.nabble.com/users%2C-please-give-us-your-opinion%3A-what-is-your-take-on-generics-with-Wicket-tp17589984p17803373.html Sent from the Wicket - User mailing list archive at Nabble.com. --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
