Andrew Robinson said the following On 4/10/2008 2:55 PM PT:
final should only be used if extending a function would cause it to
break. Forcing someone to call the super method is something that
should be in JavaDoc, not as a final keyword.
Andy already listed other uses of final.
Final's true purpose is
to create unchangeable member vars and also protect code. For example,
if I have commercial software that checks a license, it should be
final. Basically, if you don't have a reason to use final, don't use
it.
See Item 15 of Effective Java. The rule is really the opposite. If you
haven't considered all of the ways in which overriding the function may
break your class in the present and are willing to accept the
limitations on evolving your class in the future, you should not allow
the function to be overridden.
In cases like the impl package, where the class author has access to all
of the potential subclasses, these rules can be relaxed somewhat, but
the onus should still be on the potential subclasser to explain what
they want to do and why.
Final is often used in closed source because there are support issues.
By making something final, it is easier to debug. In the open source
world customers can debug into the code themselves to see what
documentation may not be clear about.
This is just not true. The final keyword is used to to prevent
subclasses from establishing contracts that the superclass does not
guarantee. It is used to prevent semantic incompatibility from
occurring between the super classes and the subclasses. It doesn't
matter if you are a subclasser extending open source or closed
source--when you pick up a new patch of the superclass, you don't want
your subclass to break. Also, note that in many cases, closed source
customers have full access to the source code for debugging.
Also note that is not simply a documentation issue--it is a class
evolution issue. The more that a superclass guarantees about its
implementation (which is what protected methods do, the less that
superclass is free to evolve its implementation.
-- Blake Sullivan
Python goes further, it has no final, everything is mutable. The idea
is to give ppl. the power they need and let them shoot themselves in
the foot if they want to.
This isn't just a matter of principle. I challenge you to author a
real world application with Trinidad, and let me know if it is
possible while letting it look professional. I found that it is not,
it is very rigid, to the point of lack of usability. Many times I
would create my own components and my own renderers because the core
ones just didn't do what I needed them to do and the renderers were
all private & final.
Take for example the table which always renders the select all and
unselect all at the top of the table and has no way to customize it.
An argument could easily be made to enhance the component API to add
these configurable points, but there is no way to anticipate them all.
If the renderer was more extendable this would be possible.
-Andrew
On Thu, Apr 10, 2008 at 3:34 PM, Scott O'Bryan <[EMAIL PROTECTED]> wrote:
The overuse of final is largely irrelevant in impl packages. The reason is
that removing a final allows the class to remain binary compatible and only
items inside of the impl package should be extending the class.
In some cases, final helps ensure an implied contract. In other words, if
something is final, you know it's implemented nowhere else. In API's I
agree with Andy, final should be used only to enforce a contract that should
not (can not) change. Most commonly this is used on immutable classes/api
but it has some other uses.
Scott
Andy Schwartz wrote:
Hi Andrew -
On Thu, Apr 10, 2008 at 4:36 PM, Andrew Robinson
<[EMAIL PROTECTED]> wrote:
I wasn't suggesting blind removal.
Okay. The use of the word "most" gave me that impression. :-)
IMO final should rarely ever be used, for open source it almost never
does
anyone any good.
Final should be used for its intended purpose. Sure, in some cases
final may be abused, but then those cases should be corrected. That
doesn't mean that final should rarely be used - it should be used when
appropriate.
Again, I don't see how open vs. closed source comes into play here.
Good API design is good API design, whether open or closed source.
I would suggest a renderer-by-renderer approach though, not
method-by-method
as that would take too long to file that many bugs.
I am not sure I understand the difference between these approaches.
At some point somebody will need to evaluate specific methods to
determine whether changes are required.
Personally I prefer the approach that Blake alluded to, which is to
open things up as the need arises. (I may have missed it, but I don't
remember seeing the particular offending cases which triggered this
discussion.)
Right now Trinidad and facelets are by far the most inflexible open
source code I have worked with. Both over-use final and both assume
that out-of-the box behavior is enough fore everyone's needs. For
Trinidad renderers, many only expose encodeAll as protected then do
most of the work in private methods. As a result a person needing to
customize a renderer has to use copy & paste (generate an entirely new
renderer using the source of the core one) which really sucks for
maintenance.
I don't understand this at all. Why would anyone do that, vs. log an
issue, submit a patch, fix the problem, revel in the magic of open
source?
Is the issue here really that the renderers as a whole are considered
off-limits to subclassing, due to the fact that they are located in
trinidadinternal (not trinidadapi)?
Andy