From: Mike Schilling on
Andreas Leitgeb wrote:
> Lew <lew(a)lewscanon.com> wrote:
>> One is to permit inheritance, and if so, design
>> the class accordingly.
>
> What makes a class "designed for inheritence"?
>
> Of course documentation - that would go without saying.
> What else? Anything else?

Being very careful about public and protected methods calling other public
and protected methods, so that overriding them selectively doesn't lead to
havoc.


From: Rzeźnik on
On 13 Paź, 01:21, Joshua Cranmer <Pidgeo...(a)verizon.invalid> wrote:
> On 10/12/2009 05:12 PM, Rzeźnik wrote:
>
> > What makes you think so? Consider SavedGame<- File. while it is clear
> > that every SavedGame is_a file you certainly do not want to expose
> > that fact to clients (if you did they could, let's say, save it
> > anywhere they like or overwrite contents blindly) while still retain
> > ability of working with files - sheer code re-use. Would you say that
> > SavedGame has_a File instead?
>
> is-a has a very specific meaning in terms of OOP. If A is-a B, that
> means every instance of class A is also an instance of class B, and,
> perhaps the most important part, every operation in class B is valid for
> objects of type A (public class Square extends Rectangle fails this part
> quite miserably).

So it is, every operation you can perform on a File is valid when
SavedGame is used as a File. I just restrain SavedGame's clients from
casting back to File. The latter example is specific because you
introduced stronger invariant in the descendant, that is perfectly ok.
If a subclass maintains stronger invariant it logically follows that
it maintains weaker invariant as well. Perhaps what is troubling you
is that not all operations valid for Rectangle remain valid when an
instance of Square is acting as a Rectangle. If so you should weaken
your criteria. You are going to lose nice substitution principle for
sure but I do not believe that inheritance is strictly about
substitution.

>
> My copy of /Effective C++/ would call what you want
> "is-implemented-in-terms-of"--which is handled by composition or (in
> C++) private inheritance.
>

Well, the problem is that in Java you cannot inherit implementation
without inheriting interface in a clean fashion. I think this might be
one of reasons that people generally frown on implementation
inheritance.


From: Mike Schilling on
Rzeznik wrote:

>>
>
> Well, the problem is that in Java you cannot inherit implementation
> without inheriting interface in a clean fashion.

Or at all :-)

>I think this might be
> one of reasons that people generally frown on implementation
> inheritance.

In fact, in Java aggregation takes the place of implementation inheritance.


From: Rzeźnik on
On 13 Paź, 01:55, "Mike Schilling" <mscottschill...(a)hotmail.com>
wrote:
> Rzeznik wrote:
> > On 12 Paz, 22:17, "Mike Schilling" <mscottschill...(a)hotmail.com>
> > wrote:
> >> Rzeznik wrote:
> >>> On 12 Paz, 21:32, "Mike Schilling" <mscottschill...(a)hotmail.com>
> >>> wrote:
>
> >>>> Another bit of useful advice from Effective Java: prefer
> >>>> aggregation. No one said you can't re-use code, but inheritance,
> >>>> particularly unintended inheritance, is not necessarily the best
> >>>> way to do it.
>
> >>> You cannot really _prefer_ one to another in general because they
> >>> represent different relationships. If this Effective Java states it
> >>> exactly so then it is another example of how misleading this book
> >>> is.
>
> >> I caution you not to judge the book by a two-word paraphrase.
>
> > Ok, you are right.
>
> > At any rate,
> >> if all you want is to re-use code, that's not an is-a relationship.
>
> > What makes you think so? Consider SavedGame <- File. while it is clear
> > that every SavedGame is_a file you certainly do not want to expose
> > that fact to clients (if you did they could, let's say, save it
> > anywhere they like or overwrite contents blindly) while still retain
> > ability of working with files - sheer code re-use. Would you say that
> > SavedGame has_a File instead?
>
> You said it yourself:: you don't want to expose to clients that SavedGame is
> a File, because this will let them call arbitrary File methods on a saved
> game.  This you don't want to derive SavedGame from File, or, to say it
> another way, there's no is-a relationship.

There is, but not exposed. Why do you think it suddenly disappeared?
But you know what I am thinking now, that because it is practically
impossible to achieve this in Java because of its very constrained
inheritance scheme, we should not worry about such cases, they'll
remain too artificial no matter how much we argue.

 What you would do instead is to
> give SavedGame a field that's a File and delegate some of the SavedGame
> methods to it (delete, possibly rename, etc.)  That's precisely a has-a
> relationship.

That's precisely awkward has-a relationship. This code would be
inevitably 'smelly', at least every operation that requires File
context. Consider:
//inheritance version
stream.save(save_game)
//delegation
first you have to define save method on SaveGame
public void save(Stream s) { s.save(this.file); }
and then use it like
save_game.save(s);

From: Rzeźnik on
On 13 Paź, 02:22, "Mike Schilling" <mscottschill...(a)hotmail.com>
wrote:
> Rzeznik wrote:
>
> > Well, the problem is that in Java you cannot inherit implementation
> > without inheriting interface in a clean fashion.
>
> Or at all :-)
>
> >I think this might be
> > one of reasons that people generally frown on implementation
> > inheritance.
>
> In fact, in Java aggregation takes the place of implementation inheritance.

Well, you can, I suppose, using protected statics but it is hideous.
Or you can live with interface "leak".