Search code examples
smalltalkpharo

How to override an existing selector in a class in another package


I'm using Pharo 5.0. In a couple of cases, I have found a limit or possibly a bug in an existing Pharo class (e.g., something in DBXTalk/Garage, or Regex-Core). I would like to be able to modify a selector or set of selectors that exist(s) in a class outside of my own project and make that part of my package.

I have found several instructions on how to create a new selector in an outside class and move that into my package (e.g., as shown in this tutorial). That's very cool. But in some cases I actually want to modify an existing selector in the outside class and have my copy of that selector override the one in the outside class when I use it. I don't wish to modify the existing 3rd party or Pharo pre-supplied package.

In GNU Smalltalk, I can do that just as a normal part of doing a class extend. For example:

Kernel.MatchingRegexResults extend [
    at: anIndex [
        "My updated version of the 'official' Kernel.MatchingRegexResults#at: selector"
        "This is part of my package so overrides the 'official' version"
        ...
    ]

    foo [
        "My new foo selector"
    ]
]

How can I do this in Pharo 5.0? I've done quite a bit of searching but couldn't find a means of doing it. The words "extend" or "override" do not appear in the Pharo by Example and Deep Into Pharo books.


Solution

  • The code in GNU Smalltalk syntax

    Kernel.MatchingRegexResults extend [
        at: anIndex [
            "method body"
        ]
        foo [
            "My new foo selector"
        ]
    ]
    

    would look like this

    !MatchingRegexResults methodsFor: 'protocol'!
    at: anIndex 
        "method body"
    !
    foo
        "My new foo selector"
    ! !
    

    in a Pharo change set that can be filed in from File Browser.

    But please note that in both cases, GNU Smalltalk and Pharo Smalltalk, you are actually replacing the original version of the method in that class.

    In GNU Smalltalk you might not be accustomed to saving the image and hence you might think that the extend syntax does not modify the original method in the original class.

    Actually it does exactly that.

    With GNU Smalltalk you typically start with the same old unmodified image each time you run gst. This is because the default place for the image in GNU Smalltalk is not writable to the normal user. So gst reads the same read-only image each time, you modify it in-memory with class definitions and extensions, your modified image only lives temporarily while your program is running, and is discarded on program exit.