From: Mike Schilling on 12 Oct 2009 19:58 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 12 Oct 2009 20:07 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 12 Oct 2009 20:22 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 12 Oct 2009 20:23 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 12 Oct 2009 20:27
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". |