The classes have a mixture of practices right now which make them very tricky to extend.
All classes seem to communicate they can be extended (i.e. they are not marked as final), but as most of them don't properly support late static binding (they use self:: and private methods), extending them will lead to unexpected results and hard-to-diagnose bugs. self:: and private should only be used in final classes, or, in more rare cases, when an extension should specifically not have access to some part sof the base class.
The solution is to either mark all of them as final (provided there is an underlying interface), or make sure they properly support extension.
I've opted for the second option in this PR, for the following reasons:
some classes were already changed from non-extensible to extensible in prior changes, so I suppose this is a wanted use case
some classes have quite a bit of logic to them, and keeping them extensible avoids completely rewriting some of these
The classes have a mixture of practices right now which make them very tricky to extend.
All classes seem to communicate they can be extended (i.e. they are not marked as
final
), but as most of them don't properly support late static binding (they useself::
andprivate
methods), extending them will lead to unexpected results and hard-to-diagnose bugs.self::
andprivate
should only be used infinal
classes, or, in more rare cases, when an extension should specifically not have access to some part sof the base class.The solution is to either mark all of them as
final
(provided there is an underlying interface), or make sure they properly support extension.I've opted for the second option in this PR, for the following reasons:
Related issue: #231