Search code examples
smalltalkpharo

Programmatically create and delete classes in Pharo Smalltalk


I'm trying to create classes from an external definition stored in a JSON file. I can create a class easily with a message like:

name := 'SomeNewClass'
Object subclass: name asSymbol
       instanceVariableNames: ''
       classVariableNames: ''
       package: 'SomeNew-Package'.

This works fine the first but if I run my code again it fails as the class already exists. I've been looking but I can't figure out how to check if a class exists and to remove it if it does?


Solution

  • Your code shouldn't fail. The problem you see must have a different cause, let me explain why.

    In (every) Smalltalk classes can be redefined for the purpouse of modifying them. Typically you will start with a simple approach on the lines of

    Object subclass: #Volcano
           instanceVariableNames: ''
           classVariableNames: ''
           package: 'SomeNew-Package'
    

    add some methods and tests and then realize you need an instance variable or two

    Object subclass: #Volcano
           instanceVariableNames: 'location active'
           classVariableNames: ''
           package: 'SomeNew-Package'
    

    In doing this, the very same class object Volcano will remain the same and your instances (if any is around) will acquire two new slots (one for location and the other for active).

    More generally, the capability of redefining a class includes all operations you might need for evolving your model:

    • Add/Remove/Rename an instance variable
    • Add/Remove/Rename a class variable
    • Add/Remove/Rename a class instance variable
    • Change the superclass
    • Rename the class
    • Move the class to another package

    None of these operations will interpret that the class already exists and cannot be redefined. On the contrary, there is a lot of infrastructure at your disposal to enable all of them in a meaningful way, which not only will reshape your class but its instances and subinstances too.

    Therefore, your particular problem needs another diagnostic. Tell us what "failure" you get so we can better understand what's happening.


    Trivial comment: A dot is missing in your code snippet for separating the two statements. It should read

    name := 'SomeNewClass'.               "<- dot added"
    Object subclass: name asSymbol
           instanceVariableNames: ''
           classVariableNames: ''
           package: 'SomeNew-Package'.    "<- final dot is ok but not required"
    

    BTW, you could have written this in a single statement:

    Object subclass: #SomeNewClass
           instanceVariableNames: ''
           classVariableNames: ''
           package: 'SomeNew-Package'