I recently had to look into a Java system where the developers used a lot of inner classes. I found it very difficult to understand the design of the system. Plus my favourite development tool (VisualAge) does not support debugging of inner classes very well. So I thought it might make sense to collect some design and implementation guidelines on how and when to use inner classes. Here are some : * if an inner class gets longer than 10 lines of java code, try to refactor the inner class into a normal class * if an inner class needs more than 2 methods, try to refactor into a normal class I appreciate any comments -- PeterGassmann ---- Refactor: merge with WhenToUseInnerClasses. See also InnerClassesAreSecondaryAbstractions. ---- I don't know if inner classes are directly comparable in Java and C++, but places where I ''would'' use inner classes in C++: * where the inner class is tied to the outer one (cf. STL iterators). * for reasons of scoping. This is usually related to the above, but given the choice of a class ClassFooForBar and Bar::Foo, I tend to go for the latter. Your comments on the size of the inner class are useful metrics, however. I tend to find that if I've got large inner class, then it's probably generally useful, and should be broken out for that reason alone. ''Surely usefulness outside the containing class is exactly the criterion, irrespective of size?'' ---- Which form of inner class is this page addressing? The two forms have very different semantics, and uses. Take this code fragment: class Nester{ static class StaticNested{ public void method(){ Nester.this.member++ ; //will not compile } } class Nested { public void method(){ Nester.this.member++ ; } } int member ; } Nester.StaticNested is invalid, this is namespace management only, whereas Nester.Nested implies object embedding: an instance of Nester.Nested can only be created within the context of an instance of Nester. ---- Ok, I mainly think about the definition of private inner classes inside a Java class, not really the anonymous inner classes (typically used to add a WindowAdapter or an ActionListener). The argument of usefulness is another important aspect, because I guess code reuse (and design) is harder if inner classes have been used to implement certain functionality. Could it be that if the system has been deliberately designed (whatever that means, any suggestions in the XP sense?), there would be less inner classes? -- PeterGassmann ---- Neither Nested nor StaticNested are anonymous. Personally I've never needed the Nested type. If I did need it, I'd be tempted to leave it static and manage the inter-class references explicitly. I have used StaticNested and I think each use conformed to the guidelines above. -- DaveHarris ---- Good use of nested classes (either kind) can greatly assist in implementation/data hiding, encapsulation and the reduction of coupling. All these should make re-use easier. What is good use of nested classes? Are there any patterns / guidelines? ---- If you could imagine reusing the code under any circumstances, anywhere, ever, don't make it an inner class. If you can't imagine reusing it, think twice more. -- JohnFarrell Use nested classes, use them a lot. Keep your name spaces as clean as you can. Use them to enforce encapsulation, hide data and implementation in them. ''What is the advantage of keeping the name space clean? If a class is not visible (which is in most tools the case with inner classes), I can't even think about reusing the class because I don't know that it exists. And reusing the implementation (or parts of it) doesn't mean I'm going to write the same stuff in the same way, but rather in a way which is similar but with significant differences. -- PeterGassmann'' Can you imagine a LISP or Scheme programmer sparing even a moment's thought over nesting procedures to achieve these things? So what if an (non-static) inner class is more difficult to re-use? ''Why are you attempting to re-use the implementation of my class?'' Are you implementing another class that does exactly the same thing, in exactly the same way? ---- Say you make it an inner class. Later you find another use for the class. Is it that big a deal to pull it out at that point? I submit that if a refactoring as trivial as that is difficult, then your "refactoring muscles" need a little stretching. After all, changing software is the norm, not the exception. -- KielHodges ''For me it's not really a question how much effort I would need to refactor. The problem is if someone else wants to reuse my code ! In that case you would need to change somebody else's code. But what if that code is in a package (say from Javasoft) where you're not allowed to change anything, or where it wouldn't be very clever to just change something? In that point I would even go further than John and say I always imagine (or hope) that my code could and should be reused. -- PeterGassmann'' Yeah, I spend as much time as anyone bitching about some of Javasoft's decisions. OTOH, I don't lose sleep over it. They made their decisions, but I need to focus on mine. As for my code being reused, I subscribe to the idea that a piece of code needs to be reused (being refactored as required) several times before it can truly be reusable. I no longer imagine or hope that my code can be reused. Instead, I work towards it simply being ''used''. If I keep it well-factored, reusability will emerge. Of course, developers of class libraries have to be directly concerned with reuse. But even libraries would be improved with a stricter rule than "imagine reusing the code ''under any circumstances, anywhere, ever''" (emphasis mine). I think that instead one should experiment with realistic, concrete scenarios. Otherwise, the result may be a class that is ''exposed'' for reuse, but is not really reusable. -- KielHodges ---- Isn't there a way to use inner classes to circumvent single inheritance? If I (for whatever reason) wanted a class to inherit from two classes (like an Impl class ''and'' java.util.Observable) could I not have the "outer" class inherit from one and a nested inner class inherit from the other? I thought inner classes could also be used to implement different views/facets of a class. For example, Smalltalk has the notion of "protocols" for its classes (at least VisualWorks does). A "protocol" is a set of method names/signatures that all have to do with the same general service or kind of services. For example, creating, accessing, printing, etc. Could not one use Java inner classes to much the same effect? -- BradAppleton ''Surely that's what Java interfaces are for? -- SteveFreeman'' Yes, but interfaces can't be applied in every situation, and Brad supposes a situation where both of the types he needs to extend are classes, not interfaces. Inner classes certainly can be used for this, and it works quite well. The situations where it is required are rare, in my experience, but when it is necessary it is easy to do with an inner class. -- GlennVanderburg ---- Some people like to implement the UnitTest as a StaticNested class of the tested class. (Say that three times quickly.) See OrganizingTestCases. -- JoeBowbeer ---- An anonymous inner class is the ''only'' way I've found to provide deferred execution (akin to blocks in Smalltalk) in Java. It lets me do, in Java, virtually everything I can do with Blocks in Smalltalk (albeit at the expense of LOTS more bloated source code). For example, I've done the collection operators "collect", "select", "detect", "reject" and "inject". I've done sorted collections with sort blocks. It appears that I can do a real exception system (by putting a hack within a hack; I use inner classes to provide block's behavior, which gives me the ability to use the set-jump trick from C, which lets me do real exceptions that can be continued, restarted, resumed, etc.). -- TomStambaugh I read an article that claimed that the people who introduced anonymous inner classes into Java were ex-Schemers. It seems like all of our ideas came from a very few roots. ''A very wise and older mentor once told me that "everything was invented at Xerox PARC. Period."'' I have been wondering whether using InnerClassesAsClosures were, for a Java programmer, a form of digging TooDeepIntoTheBagOfTricks. ''Please see MultiplyNestedClasses; can that also be a form of digging TooDeepIntoTheBagOfTricks?'' ---- Don't we have ReFactoring? Sometimes I make an inner class, then I extract a method then I move the method to another class then I move the inner class to be an outer class. You can always change it. -- BrianRobinson ---- One potential use of inner classes is to help define the interface of a class. For example, java.awt.Component is the basic graphical component. Its event/listener interface is defined by java.awt.event.ComponentEvent and java.awt.event.ComponentListener (and ComponentAdapter). Though the "event" component features are not specified directly as part of the class in Java, the Event and Listener types could have been defined as static inner classes. This makes sense because Component{Event,Listener} are not intended for use outside of the context of using a Component. Having the classes themselves inside the namespace of Component makes their use more clear. -- ChrisDailey ---- I realize this discussion has been focused on Java, but...there are some interesting uses of full-sized nested classes to implement what one person has called "MixIn layers". The outer mixin class subclasses (via templates) the base class, and arranges to have some of its member classes subclass members of the base class. The cleverness is that the nested subclass has the same name as its nested superclass (that is, Mixin::Foo is a subclass of Base::Foo), so you can add additional mixins and not have to worry about what mixins have already been applied. Interesting stuff, although it really stress-tests the C++ compiler's template handling. -- BillTrost ---- ''I found it very difficult to understand the design of the system. Plus my favourite development tool (VisualAge) does not support debugging of inner classes very well.'' perhaps the latter is the real problem here? if you regularly used a tool that coped with inner classes would it be less of an issue?