Path: news.daimi.aau.dk!news-feed.inet.tele.dk!cpk-news-hub1.bbnplanet.com!cam-news-hub1.bbnplanet.com!news.bbnplanet.com!prodigy.com!nntp.earthlink.net!usenet From: Jay Martin Newsgroups: comp.lang.java.advocacy,comp.lang.beta Subject: Re: inner classes are hideous Date: Wed, 13 Aug 1997 15:37:52 -0700 Organization: EarthLink Network, Inc. Lines: 165 Message-ID: <33F23740.4C64@earthlink.net> References: <01bc958d$10ec9a00$3fe82299@mayura> <33EA55A0.DEE@earthlink.net> <33EA63AB.2DDB@earthlink.net> <33EC29CA.7CD5@earthlink.net> <5shqsc$fq$1@gjallar.daimi.aau.dk> <33ECD6E7.46C9@earthlink.net> <33F02A5A.2234@cs.auc.dk> NNTP-Posting-Host: pool030-max6.gardena-ca-us.dialup.earthlink.net Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-Mailer: Mozilla 3.03 (WinNT; I) Xref: news.daimi.aau.dk comp.lang.java.advocacy:13411 comp.lang.beta:11240 Kasper Osterbye writes: > But returning to inner classes. > Inner classes are not too interesing without anonymous classes. > Perhaps in practice anonymous classes are much more practically > useful than inner classes. > > The following code is from > http://java.sun.com/docs/books/javaprog/1.1Update.html: > > "When you are writing simple subclasses or implementations of > interfaces, creating a bunch of classes for each trivial class can be > awkward. Anonymous classes are a convenient short form of inner > classes that have no name, only an implementation that is specified > right along with the new. Suppose you want to create a simple > Observer object (see page 233) that keeps a history of the events > stored in a field of your object. The following would do this > directly and simply: > > > private Vector history = new Vector(); > > public void watch(Observable o) { > o.addObserver(new Observer() { > public void update(Observable o, Object arg) { >!! OuterClass.this.history.addElement(arg); > } > }); > } > Note: I evily added "OuterClass.this" to the original code. I could see an "evil" coding standard actually requiring this. Here are some alternative ways (language design wise) to do the same thing as inner classes: //--------------------------------------------------------------- // Alternate #1: Subclassing Observable. // Assumes 1-Class <--> 1-Observer. //--------------------------------------------------------------- private Vector history = new Vector(); public void update(Observable o, Object arg) { history.addElement(arg); } public void watch(Observable o) { o.addObserver(this); } //---------------------------------------------------------------- // Alternative #2: Boring C++ style. No "inner classes" needed. //---------------------------------------------------------------- private Vector history = new Vector(); class MyObserver extends Observer { public Observer(OuterClass outer) { outer.this = this; } public void update(Observable o, Object arg) { outer.history.addElement(arg); private OuterClass outer; }; public void watch(Observable o) { o.addObserver(new MyObserver(this)); }; //----------------------------------------------------------- // Alternate #3: Callback Using a "Object-Method Pointer". // language style feature. // "&this.update()" is a ref to method with attached object. // Syntax to be polished later. //----------------------------------------------------------- private Vector history = new Vector(); public void update(Observable o, Object arg) { history.addElement(arg); } public void watch(Observable o) { o.addObserver(&this.update()); } Even in this trivial example, where inner/anonymous is at its optimum is trivial to do without the feature. Anonoymous classes just look worse with longer(code) code. > The addObserver has an embedded new of an anonymous class that > implements the Observer interface, implicitly extending Object. This > anonymous class implements update by adding an element to the > enclosing object's history vector. The compiler creates an unnamed > (hence "anonymous") class that overrides update as specified." > > The idea is the now classic pattern of separating iterators from > collections. Same sort of thing. Example deleted. > It can be argued that there is not much interesting here, as one > could have created a new class Fooey (as on page 25). However, if you > program uses two ES objects, and they need to handle events > differently, then you need a Fooey1 and a Fooey2 class. Inner- and > anonymous classes solves this. Doesn't really "solve" anything just makes it more convienient. And "handy" and "convienent" does not usually mean "good for software engineering". > In general, your references to blockstructure "nesting is for the > birds" etc. is hitting on an other nail, blockstructure is not to be > used for modularization aka. abstract datatypes. This I believe is > true. On the other hand, there are also problems in using class > structure for modularization as can be seen with the friend classes > from C++, and their counterpart of file scopes or "no encapsulation". > This does not mean that classes are a bad idea, only that there are > short commings. Block structure sometimes solves the friend problem > (letting the friend be an inner class), sometimes it does not. > > In my experience there is nothing unnatural about block structure to > beginners. They are used to thinking that many concepts need a context > to be understood. Also anonymous classes are easy to understand: "I want > one like that, only this little thing slightly different". I see little reason to add a "containment(inner class nesting) hierarchy" to be confused with the existing "class hierarchy". Also C/C++ programmers aren't used to nesting. I think nesting functions/classes larger than a certain size is confusing and undeciplined. It doesn't scale during maintainance when alot of code is added which ruins the locality of the code (i.e no longer fits on one page on the screen). Then there is there are reuse issues. I remember those CS Pascal test questions that used nesting in a trick and complex way and asked "what does this output". Probably a better questions is: How many bullets should you fire into the head of the programmer that wrote this garbage? > Now I am just waiting for Java to reintroduce the idea of nested > procedures, so that I can place my "supporter methods" within the > method they support, so that it is clear from the code and can be > checked be the compiler that supporter methods are only called by the > one they are expected to support. The way things are going it seems readily apparent that such (or any other fashionable features) will be added to Java in short time. Jay