Whose meta-analysis came up with that? Like to see that.
> Ironically, almost anything added after the base class (and maybe some abstracts above that) is a cross cutting concern added after the core functionality is established.
That's a bold statement (unless you have a novel definition of "cross cutting concerns") and actually backwards: The super provides the generalization and subs specialize. A cross cutting concern is a 'general' concern. AFAIK, cross cutting concern is a term originated by the inventor of AOP, and the typical garden variety CCC deals with matters that rarely have anything to do with the types to which it is applied. (Debug log in-args is a garden variety example.)
You'll have to dig into each language that has expanded it's composition capability and the reasoning, but the outcome is self-evident. Many languages started with simple inheritance (eg PHP, Java, VB, C++, et al) and expanded composability mechanisms over time.
> That's a bold statement (unless you have a novel definition of "cross cutting concerns") and actually backwards: ... A cross cutting concern is a 'general' concern.
I'm not going to argue about how you wish to redefine things.
Good luck with whatever.
I agree that inheritance creates a lot more problems, but the usages of non-static methods and internal state even in classes with no usage of inheritance can feel just as bad, when you have a high level method utilizing instantiated objects. Internal state as a whole can be avoided fairly often
some_state.do_stuff()
do_stuff(some_state)OTOH, the second one would be much better (and imply immutability) if it were written as
new_state = do_stuff(some_state)
But it'd also allocate a new state.let's have do_stuff=square and some_state=2.
What does square(2) imply?
I know there are mechanisms to avoid this, but many times they are opt-in rather than opt-out, and so it encourages this access-to-state propagation through the codebase where you have far reaching consequences
This is primarily because of inheritance, which seems counter-intuitive. In a meta-analysis of OOP-based designs, inheritance is used as the primary form of composition with other strategies being either last-resort or added later when the inheritance is already deeply embedded as part of the design.
Inheritance is a brittle form of a composition (no-reinherit) that nests state in a deep tree-like type system, rather than isolating it into attachable modules. Most OOP-based languages have slowly had to adopt additional forms of composition, as inheritance is not suited well for cross cutting concerns. Ironically, almost anything added after the base class (and maybe some abstracts above that) is a cross cutting concern added after the core functionality is established.