Polymorphic method signatures
A few days ago, I was working on a new feature at work. The specifics aren’t important, but it’s worth mentioning that they involve object-oriented inheritance.
There was a method that all the classes shared, which takes a single argument and returns a boolean value. In the case of the base class, it was hardcoded, and therefore never used the argument. For that reason, the argument was made optional.
One class overrode this and did use the argument, though it kept it optional and opted for some confusing branches when the argument is not passed in. I was overriding this method for another class, and I absolutely required the argument.
Well, that caused some buggy behaviour, because some places in the codebase were already calling this method without an argument. I was forced to change my version of the method to accomodate a call without the required argument.
Of course, that wasn’t sufficient, because the line causing the issue wanted the opposite behaviour without passing in the argument, but there were some security flaws with doing it that way (you can probably guess what we were passing in, and probably what the method does now, which I was trying to avoid, because it’s not great, but eh…).
Luckily, in this case, I could just change the line causing the issue to take in the argument, but there is at least one place in the codebase that almost couldn’t have happened (I could easily see a version of that part of the codebase that just did not have the argument we were looking for, and it’s from a gem, so it would have been bad to change).
It probably never occurred to whoever wrote the original base method, but here are two things to take away from this:
- Keep your shared method arguments consistent. If an argument is optional somewhere, it should be optional somewhere else.
- Probably don’t use optional arguments with base methods in the first place, as you never know when that argument will be required for an overriding class.