I wrote a class called Container that processes hierarchies (as classes are visible to the user) and converts them internally to a flat array. Thus, for the outside of the container, it looks like a hierarchy of containers, each with parent and child nodes.
This is the functionality that I want to add to specific classes. For example, the Widget class, it must have the same functionality as in the Container.
I could let Widget inherit from Container. A container is now defined as a class with this (), data member, member functions, invariant, and unittests. A container contains an array of containers, so there is one mistake in the design: what if Foobar also inherits Container, and we add Foobar elements to the Widget container? This should be prohibited. They share the same base class, but they are fundamentally different things with different goals ... they just seem to have some functionality.
Defining a container as an interface is not possible because it contains data members (and does not solve the problem). There is no definition of Container as mixin, since we have this () functionality too (or how will it work out?). Visibility attributes for functions in mixins also do not work. Also, I cannot pass it the this argument to the Widget class, because it must be the first element of a flat array.
I was thinking of giving Container a template argument, specifying in which container it is:
abstract class Container(T) { ... T[] elements; } class Widget: Container!Widget { }
This gives an error: the container of the class .__ unittest2.Widget base class is redirected to the container.
How would you implement this? I could also add checks to the Container, which ensures that when the child is added, it is of the same type as the parent. But how can I check this?
abstract class Container { void add(Container child) {
EDIT: Even if the first part of the code does not signal an error, it still does not solve the problem. I cannot arbitrarily add more functionality, since only one base class is allowed. The rest should be interfaces that are fundamentally different from each other. Interfaces guarantee that the derived class has certain functionality; they do not add the functionality itself.
This should be allowed with (template) mixes. But mixins cannot add code to the constructor (only replace if not defined), cannot add code to invariant (invariant with several temporary values), cannot indicate the visibility of a member function or use other class / structure keywords ...