Personally, in such cases I used a differently named method. A subclass may still decide to just call toString in it, but in cases where all subclasses of a class need a
toString, there usually is a better name.
If you require the
toString method to be overloaded, there’s a good chance anyway, that you also need a specific format, and in that case I wouldn’t want the method to be available on all types, even the ones that are not subtypes of my abstract class. That’s also one of the main reasons why I switched to using the
Show typeclass from cats, because it’s only available for types that actually do implement it and does not have a default for all others.
Edit: oh, another point: case classes will generate a
toString, which will count as overriding, so you can still forget to override it, although the default will be more useful.