Originally posted by Peter Chase:
But at least one use of "final" for methods is still very valid, I think. That is where you use "final" to say which parts of a class are suitable for overriding, and which aren't. Sometimes, that just helps to make the code more self-documenting and sometimes it is actually necessary, to prevent maintenance programmers doing something really dumb. For instance, sometimes a particular method might be doing crucial operations on some private data. An override couldn't possibly do the right thing, and making the method "final" enforces this.
ugh. i posted that original article late at night, when tired; now i'm writing this defense of it early in the morning, when tired. i need to fix my lifestyle, i think.
anyway. i'm not entirely clear on what Jim Yingst meant by "nonliteral constants", but if it's got something to do with immutable objects, i suspect i'd agree with such a usage of "final". that sounds like something i would have meant to include when i said "literal constants", but i was too worn out to phrase myself better... if you're declaring a thing "final" because it would be a clear error in logic under the design rules of your program to ever redefine that thing, or assign it a new value, then most likely i'd have no problem with that. that's what i use constants for, as do we all, i believe.
but i would not agree with declaring methods or classes "final", at very least not if they're visible outside your project. if someone else can see and use the thing, then that someone ought to be able to override or redefine the said thing, at least at their own risk.
i say that for two reasons. one is to do with communication, the other with design principles.
one: "final" is a compiler directive, a thing used to tell the bytecode compiler what to do - so using it to tell humans what's wise and prudent to do is a bad fit for it. if a method or field really shouldn't be overridden or redefined, by all means say so in the javadoc, or in a README, or both - tell your human users that this-or-that part of your code wasn't designed or meant to be changed, and that if they should try to do it anyway, they're on their own and you won't support them.
"final" can't really help you there, anyway. it's only a compiler directive, and the only thing that ever really obeys it is the bytecode compiler; humans can always outsmart compilers, even when they really oughtn't. if somebody
really, really wants to extend your "final" class, they'll find a way, by hook or by crook; all your declaration will truly achieve then is to annoy your users.
two: i feel that making something "public" that isn't fit to be overridden is an information hiding violation. things that could badly break your code in unpredictable or surprising ways if they were ever to be modified should be considered implementation details, and hidden away (as far as possible) out of public view; don't expose them to your users. if you
do choose to expose something,
you should be able to trust your users to modify it.
(if your users simply aren't trustworthy, you've got bigger problems than "final" can fix, anyway.
most users of code are adult enough that they can either be trusted to do the right thing, or to take their bruises when they don't; using a compiler directive to deal with such people seems mildly insulting to me, as if you were assuming all your users were mere compilers.)
three: er. my
three reasons are... (shades of Monty Python). anyway, thirdly, i feel that "final" - since it's a compiler declaration - is best fit only to prevent people from doing what would be logic errors if they were doable. but that presumes you know what the logic is. when we're talking about constants - either literal primitives, or objects that should properly be immutable - then, usually, we do know, and we can prove that modifying one of those would lead to such-and-such errors in our implementation; "final" is a good match for preventing such errors.
but when talking about extending classes and overriding methods, we can't be sure of that any longer - because the user who wishes to do that may be laboring under entirely different business restrictions;
their logic may not be ours. therefore, they should be allowed to change things as they may need to, since we can't predict and accommodate every potential use and application of our code in every situation ever. to attempt to restrict such usage only makes our own code less useful to others, which is a shame. if our code really isn't fit for such extensions - well, document that in a Javadoc and/or README, and let the users take it from there; if they try to extend the code anyway, they're on their own.
they're adults, they can handle the responsibility. if they're
not adults... well, then it's unlikely they'll kill anybody by breaking your computer code, anyway, right?