final methods and classes

  • Thread starter Lionel van den Berg
  • Start date
L

Lionel van den Berg

Hi all,

Just wondering what arguments there are out there for making methods
and classes final when they are not expected to be overridden/
extended? Typically I would make them final, but when I'm doing code
reviews I don't raise this as an issue because I see it is relatively
trivial.

Thoughts?

Thanks

Lionel.

P.S. pretty hard to filter through the crap on this group now :(.
 
R

Rzeźnik

Hi all,

Just wondering what arguments there are out there for making methods
and classes final when they are not expected to be overridden/
extended? Typically I would make them final, but when I'm doing code
reviews I don't raise this as an issue because I see it is relatively
trivial.

Thoughts?

Yes, a few :)
First of all: you answered your question already - it is done for
preventing subclasses from redefining them. So it is a mechanism of
enforcing architectural constraints in code. Let's add, very dangerous
one because a mistake here may seriously cripple code re-usability.
There were times when it was used as optimization technique - final
methods need not use polymorphic dispatching, but this technique's
become obsolete, modern VMs know whether overriding method exists or
not, so they can (and will) ignore 'final' declarations.
 
M

Mike Schilling

Lionel said:
Hi all,

Just wondering what arguments there are out there for making methods
and classes final when they are not expected to be overridden/
extended? Typically I would make them final, but when I'm doing code
reviews I don't raise this as an issue because I see it is
relatively
trivial.

Some classes have not been designed to be extensible (either as a
deliberate choice or because the time wasn't taken to make
extensibility work correctly.) For instance, a class that has only
static members should in general not be subclassed, nor should a class
that has complex interactions among its public and protected methods
[1]. "final" can signal either of those.

Likewise, classes can be designed for only some methods to be
extensible. For example, in the programming-by-contract style:

public final void method()
{
// check preconditions
...

// do the thing
doMethod();

// check postconditions
...
}

protected abstract void doMethod();

Here you enforce the convention that the method is extended by
overriding doMethod() rather than method() by making the former final.
That is, you welcome different implementations of what the method
does, but you frown on classes that skip the pre- and post-checks.

1. The functionality of such a class can be extended using aggregation
with far more safety and robustness.
 
M

markspace

Mike said:
Some classes have not been designed to be extensible (either as a
deliberate choice or because the time wasn't taken to make
extensibility work correctly.)


This is the one I would emphasize. "Either design for inheritance or
prevent it." Effective Java, I believe, by Joshua Bloch.

Inheritance is a sticky issue and can lead to some surprising
situations. It's best to consider all the issues involved and to
convince yourself that you've addressed each. (Bloch has a whole
chapter of "tips" devoted to inheritance issues, iirc.) If you don't go
through that process, or you do and decide that you cannot support
inheritance, then make the class final.

Another issue is multi-threading, thread safety and the whole foreign
method bug-a-boo. Use private methods when you can, but if you must,
making a public method final is the only way to guarantee that an
instance method does not suddenly become a foreign method.
 
L

Lew

Sorry about the accidental post. I had intended to write:

Excellent link, Arne. However, that very article gives many good reasons for
using the 'final' keyword, contradicting your notion that there aren't good
reasons for it.

From an API writer's perspective, that is, anyone writing classes intended to
be used, 'final' on a class or method indicates that it should not, and
therefore cannot be extended / overridden. As Mr. Goetz said in the
referenced article, this decision should be documented (in the Javadocs).

Josh Bloch in /Effective Java/ suggests that one should prefer composition to
inheritance, and that inheritance is somewhat abused. ("Design and document
for inheritance or else prohibit it") He advises to make classes final unless
you explicitly and properly make them heritable.
 
L

Lionel van den Berg

Sorry about the accidental post.  I had intended to write:

Excellent link, Arne.  However, that very article gives many good reasons for
using the 'final' keyword, contradicting your notion that there aren't good
reasons for it.

 From an API writer's perspective, that is, anyone writing classes intended to
be used, 'final' on a class or method indicates that it should not, and
therefore cannot be extended / overridden.  As Mr. Goetz said in the
referenced article, this decision should be documented (in the Javadocs).

Josh Bloch in /Effective Java/ suggests that one should prefer composition to
inheritance, and that inheritance is somewhat abused.  ("Design and document
for inheritance or else prohibit it")  He advises to make classes final unless
you explicitly and properly make them heritable.

Some excellent comments and discussion here.

I am of the above view, if I see inheritance or consider using it I
scrutinise the design to death to make sure inheritance really is the
appropriate solution. The majority of classes have no need to be
inherited.

I have in the past used inheritance to find later how confusing it can
make a design, and now I'm seeing it used frequently for no reason
other than code re-use, which is definitely bad.

Thanks for the comments and links.

Lionel.
 
M

Mike Schilling

markspace said:
This is the one I would emphasize. "Either design for inheritance
or
prevent it." Effective Java, I believe, by Joshua Bloch.

There's a rule of thumb I was taught long ago that one shouldn't
derive one concrete class from another. I've found it to be excellent
advice. I can't explain particularly well why doing so is a bad idea
in general, but whenever I've been tempted to break the rule, I've
found that creating an abstract superclass (or a hierarchy of such
superclasses) from which all concrete classes are derived has solved
problems the concrete-derived-from-concrete design created. I don't
think it's far wrong to say:

Declare all concrete classes as final.
 
R

Roedy Green

Just wondering what arguments there are out there for making methods
and classes final when they are not expected to be overridden/
extended? Typically I would make them final, but when I'm doing code
reviews I don't raise this as an issue because I see it is relatively
trivial.

see http://mindprod.com/jgloss/final.html

For APIs you don't publish, I think you should make anything final you
can for documentation purposes.
--
Roedy Green Canadian Mind Products
http://mindprod.com

I advocate that super programmers who can juggle vastly more complex balls than average guys can, should be banned, by management, from dragging the average crowd into system complexity zones where the whole team will start to drown.
~ Jan V.
 
R

Rzeźnik

Some excellent comments and discussion here.

I am of the above view, if I see inheritance or consider using it I
scrutinise the design to death to make sure inheritance really is the
appropriate solution. The majority of classes have no need to be
inherited.

I have in the past used inheritance to find later how confusing it can
make a design, and now I'm seeing it used frequently for no reason
other than code re-use, which is definitely bad.

No Lionel, it's oversimplification. So called implementation
inheritance or utility inheritance has its uses. Probably you perceive
it as bad because it is mostly used in systems that have multiple
inheritance or mixins (consider ArrayStack <- Stack, Array which
presumably inherits interface from Stack and implementation from
Array). But even in a language limited to single inheritance you
should find good uses for this kind of inheritance. One such example
might be, common in Java world, constants inheritance. Another might
be Sun's SqlDate <- Date (although they have been widely criticized
for this, but that's had nothing to do with their choice of
inheritance per se. They just screwed interchangeability up) I really
suggest you should read B.Meyer "Object Oriented Software
Construction". The author gives very precise inheritance taxonomy
which you might find interesting.
 
R

Rzeźnik

There's a rule of thumb I was taught long ago that one shouldn't
derive one concrete class from another.  I've found it to be excellent
advice.  I can't explain particularly well why doing so is a bad idea
in general, but whenever I've been tempted to break the rule, I've
found that creating an abstract superclass (or a hierarchy of such
superclasses) from which all concrete classes are derived has solved
problems the concrete-derived-from-concrete design created.  I don't
think it's far wrong to say:

  Declare all concrete classes as final.
.... if you are ominous

If you are ominous then this idea is great. I'd bet you are not. In
fact declaring everything as final is worse than most things you can
do to cripple program development. IMO every time you are
_introducing_ final you have to think deeply. You propose something
opposite, final by default, which effectively throws away the open-
closed principle which lies at the foundation of OOP. If no concrete
class can be redefined, then either your implementation has to be
perfect, so no need ever arises to modify its behavior, or you provide
no implementations at all. Both cases are quite useless from your
clients perspective. Consider: Checkbox <- Button, SecureConnection <-
Connection. Now you are proposing to reject similar cases, so every
Button implementation will have to either be catch-all scheme (not
possible) or go to great lengths to abstract every functionality by
means of composition/decoration (either not possible or hardly doable
considering that every contained type still suffers from the same
illness - one concrete type only). Furthermore, in my opinion program
maintenance is done mostly "near leaves" (of inheritance tree) - most
ADTs have their implementations already defined at this stage.
 
R

Rzeźnik

Mike Schilling wrote:
Another issue is multi-threading, thread safety and the whole foreign
method bug-a-boo.  

Yep, these are very awkward to deal with in the presence of
inheritance. There are research-level languages which make an attempt
to compose these two concepts: DRAGOON and SINA to name a few. In
Eiffel one can find quite interesting, but not so theoretically
powerful, concept either (active/passive objects)
 
M

Mike Schilling

Rzeznik said:
... if you are ominous

If you are ominous then this idea is great. I'd bet you are not.

I can be pretty threatening at times. Or do you mean "omniscient"?
 
L

Lew

Rzeźnik said:
Array). But even in a language limited to single inheritance you
should find good uses for this kind of inheritance. One such example
might be, common in Java world, constants inheritance. Another might

I know of no good use of constant inheritance. Constants are declared
generally as static variables, which are not inherited, exactly, nor should be.
be Sun's SqlDate [sic] <- Date (although they have been widely criticized
for this, but that's had nothing to do with their choice of
inheritance per se. They just screwed interchangeability up) I really

Terrible example, as it demonstrates why not to inherit a concrete class.

But it's hard to say because java.util.Date is such a screwed-up class to
start with. Even if classes should sometimes be heritable, screwed-up classes
definitely should not be. Using java.sql.Date as an example actually
undermines your point.

And the standard Java API does not have a class 'SqlDate'.
 
L

Lew

Rzeźnik said:
... if you are ominous

I don't understand.
If you are ominous [?] then this idea is great. I'd bet you are not. In
fact declaring everything as final is worse than most things you can
do to cripple program development. IMO every time you are
_introducing_ final you have to think deeply.

Every time you omit 'final' in a class declaration you should consider
carefully. Read the item in /Effective Java/ referenced upthread for a
thorough explanation of why to prefer non-heritability.

As an API writer (that is, one who writes a class intended for use) one should
control how the API is used, not predict it.
 
L

Lew

Rzeźnik said:
Yep, these are very awkward to deal with in the presence of
inheritance. There are research-level languages which make an attempt
to compose these two concepts: DRAGOON and SINA to name a few. In
Eiffel one can find quite interesting, but not so theoretically
powerful, concept either (active/passive objects)

Which isn't so very helpful when programming in Java.
 
R

Rzeźnik

Rzeźnik said:
Array). But even in a language limited to single inheritance you
should find good uses for this kind of inheritance. One such example
might be, common in Java world, constants inheritance. Another might

I know of no good use of constant inheritance.  Constants are declared
generally as static variables, which are not inherited, exactly, nor should be.
be Sun's SqlDate [sic] <- Date (although they have been widely criticized
for this, but that's had nothing to do with their choice of
inheritance per se. They just screwed interchangeability up)  I really

Terrible example, as it demonstrates why not to inherit a concrete class.

But it's hard to say because java.util.Date is such a screwed-up class to
start with.  Even if classes should sometimes be heritable, screwed-up classes
definitely should not be.  Using java.sql.Date as an example actually
undermines your point.

???
Well, I don't know what is your point against java.util.Date and I do
not know what makes my example so bad in your eyes. It is perfectly
valid example of concept of implementation inheritance (how it was
actually carried out is irrelevant)
And the standard Java API does not have a class 'SqlDate'.

We all know what we are talking about.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,072
Latest member
trafficcone

Latest Threads

Top