From: AndyW on
On Tue, 20 Feb 2007 14:22:13 GMT, Michael Feathers
<mfeathers(a)objectmentor.com> wrote:

>
>Funny thing about *final*. It looks like a great feature. You get to
>decide whether a class can have subclasses or whether a method can be
>overridden, but now I think it is too easy to abuse. Sure, if you have
>control over all of your code, you can make things *final* and remove
>*final* when it gets in the way, but if you develop code for someone
>else you can easily put them in a situation where it is hard or
>impossible to write unit tests for particular areas of code.
>
>Classic example:
>
>You have a class A from Vendor X and it has 15 methods. One of your
>classes, B, uses it and one of the methods that it uses has some
>sideffect you wouldn't like to see happen in a test. You'd like to mock
>out that method on A, and you could by subclassing A and overriding the
>method, but if Vendor X made A or that method of A final, your options
>are limited.
>
>----
>Michael Feathers
>www.objectmentor.com
>michaelfeathers.typepad.com
>author of: Working Effectively with Legacy Code (Prentice Hall 2005)

To be different from probably the other posts that may follow.

I would suggest that if something can be derived from further, it isnt
an object but a form of abstraction (either a concrete abstraction
that can have an instance or a virtual abstraction that cannot be
instantiated).

If one really thinks about it from a purist perspective. Objects
cannot be derived from further although they can be combined with
other objects (although many people do not hold this view and it is my
own).

So, the final keyword really only should be valid if the entity cannot
be derived from further anyhow, which other than acting as an
indicator to make this clear, really I think serves no real purpose.


----------------
AndyW,
Mercenary Software Developer
From: Jerry Coffin on
In article <puDCh.148$PL.26(a)newsread4.news.pas.earthlink.net>,
mfeathers(a)objectmentor.com says...
>
> Funny thing about *final*. It looks like a great feature. You get to
> decide whether a class can have subclasses or whether a method can be
> overridden, but now I think it is too easy to abuse. Sure, if you have
> control over all of your code, you can make things *final* and remove
> *final* when it gets in the way, but if you develop code for someone
> else you can easily put them in a situation where it is hard or
> impossible to write unit tests for particular areas of code.

[ ... ]

Java's final strikes me as an example of second-system effect.
Especially early on, C++ really could have used final or something very
similar. In fact, upon close analysis Scott Meyers once stated (mostly
correctly, IMO) that in a C++ hierarchy, classes should divide into two
groups, with no overlap: abstract classes that can't be instantiated,
and leaf classes from which no further deriviation is allowed. FWIW, he
originally wrote about this in the July/August 1994 issue of The C++
Report. Doing a bit of looking, he also posted a bit about it on Usenet
around the same time:

http://groups.google.com/group/comp.lang.c++/msg/dc1a601560ba8dcf

Had it been available in early C++, a final keyword probably would have
been quite useful. In fact, I would tend to agree with Scott Meyers that
most (perhaps all) concrete classes should have been treated as final.
This problem hasn't entirely disappeared from C++, but large hierarchies
mostly have, so its utility would now be much more limited (at most).

Java eliminated most (if not all) of the reasons final would have been a
good thing in C++, then included final anyway. In Java, final is
associated with problems far more than solutions.

--
Later,
Jerry.

The universe is a figment of its own imagination.
From: Daniel T. on
Michael Feathers <mfeathers(a)objectmentor.com> wrote:

> Funny thing about *final*. It looks like a great feature. You get to
> decide whether a class can have subclasses or whether a method can be
> overridden, but now I think it is too easy to abuse. Sure, if you have
> control over all of your code, you can make things *final* and remove
> *final* when it gets in the way, but if you develop code for someone
> else you can easily put them in a situation where it is hard or
> impossible to write unit tests for particular areas of code.

As far as the "final" keyword I think it should be an automatic
designation, not something the programmer decides on. In essence, I
agree with Jerry Coffin. If objects can be made from the class, then
they should be final by default. Such an idea would make the brittle
base class problem go away.

> Classic example:
>
> You have a class A from Vendor X and it has 15 methods. One of your
> classes, B, uses it and one of the methods that it uses has some
> sideffect you wouldn't like to see happen in a test. You'd like to mock
> out that method on A, and you could by subclassing A and overriding the
> method, but if Vendor X made A or that method of A final, your options
> are limited.

I agree with HS Lahman about the example, but that still leaves the
question as to what to do in that situation, and the answer is an
adaptor. Vendor X apparently did not provide a suitable abstraction
("interface") for class A. So you need to write your class B to use an
interface "InterfaceA", one subclass will contain an A object and rout
all calls to it, while the other subclass intercepts calls to the
problematic methods.
From: Daniel T. on
Michael Feathers <mfeathers(a)objectmentor.com> wrote:

> I'd agree there if popular languages allowed you a way to retrofit
> interfaces on classes that are shipped without them. Unless you have
> that feature, you're stuck.
>
> Your comments do make it clear, though, that it isn't final per se
> that's the issue. It's final without any form of substitution that's
> problematic.

I understand the misreading but your comment brings to light a rather
glaring oddity to me... The languages (like Objective-C and I think
Ruby) that allow one to add new methods to a class are exactly the kinds
of languages (dynamic-typed) that don't need such a feature.

It would be nice to see a static-typed language that allows one to
retrofit an interface onto an already written class without modifying
that class. That would solve a lot of problems that people have in
static-typed languages IMHO.
From: Dmitry A. Kazakov on
On Wed, 21 Feb 2007 17:46:12 GMT, Daniel T. wrote:

> It would be nice to see a static-typed language that allows one to
> retrofit an interface onto an already written class without modifying
> that class.

Only two things are needed for that: supertyping and multiple
inheritance/export. The pattern is very simple:

T -> S -> I

T is the type. I is the interface (or even a concrete type). S is a new
proxy type which is a supertype of T and a subtype of (implements) I. S
could be anonymous. Because -> is transitive, so T -> I. Done.

> That would solve a lot of problems that people have in
> static-typed languages IMHO.

Yes!

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de