Search code examples
smalltalkinner-classes

inner classes in smalltalk


I wonder why smalltalk doesn't make use of java-style inner class. This mechanism effectively allows you to define a new instance of a new class, on-the-fly, where you need it, when you need it. It comes handy when you need an object conforming to some specific protocol but you don't want to create a normal class for it, because of its temporary and local nature being very implementation specific. As far I know, it could be done easily, since syntax for subclassing is standard message sending. And you can pass self to it so it has the notion of the "outer" object. The only issue is anonymousity - the class should not be present in object browser and must be garbage collected when no instances of it exit. The question is: Has anyone thought of this?


Solution

  • There are really two answers here:

    1 - Yes, it is not hard to create anonymous classes that automatically get garbage collected. In Squeak they are called "uniclasses" because the typical use case is for adding methods to a single object. Systems that use this are for example Etoys and Tweak (although in Etoys the classes are actually put into the SystemDict for historic reasons). Here's some Squeak code I recently used for it:

    newClass := ClassBuilder new
        newSubclassOf: baseClass
        type: baseClass typeOfClass
        instanceVariables: instVars
        from: nil.
    baseClass removeSubclass: newClass.
    ^newClass
    

    Typically, you would add a convenience method to do this. You can can then add methods, and create an instance, and when all instances are gone, the class will be gc'ed too.

    Note that in Java, the class object is not gc'ed - an inner class is compiled exactly like a regular class, it's only hidden by the compiler. In contrast, in Smalltalk this all happens at runtime, even the compiling of new methods for this class, which makes it comparatively inefficient. There is a much better way to create anonymous precompiled behavior, which brings us to answer 2:

    2 - Even though it's not hard, it's rarely used in Smalltalk. The reason for that is that Smalltalk has a much more convenient mechanism. Inner classes in Java are most often used for making up a method on the fly implementing a specific interface. The inner class declaration is only needed to make the compiler happy for type safety. In Smalltalk, you simply use block closures. This lets you create behavior on the fly that you can pass around. The system libraries are structured in a way to make use of block closures.

    I personally never felt that inner classes were something Smalltalk needed.