I just hit the very basic problem in OOP and I cannot see any working solution except postponing appropriate check until run time.
It is pretty clear notion of an action "do something with value of the same type" no matter what means given language provides. Consider
Equals in C# which in simplest form is "is this object is equal to that object". Or
Comparable<T> also in C#. No matter where you start such hierarchy the following is valid:
Comparable<T> --> Animal --> Cat +---> Dog
And the problem:
Animal cat = new Cat(); Animal dog = new Dog(); cat.Compare(dog); // ERR
How to design a language from scratch in such way, that the above line would give an error in compile time?
So far I introduced type Self, which gives clear meaning what you would like to do within a type:
type Animal ... compare(cmp Self) ... type Cat ... compare(cmp Self) ... type Dog ... compare(cmp Self) ...
but it is not enough to avoid the problem with cross passing objects.
Can it be done? Maybe it was already done? How?
I already considered such extreme measures as two kinds of inheriting methods -- with virtual mechanism and not -- and calling them appropriately, but this in turn excludes the generic types (unless generic types are implemented as in C++ -- as templates). With only 2 level of inheritance it could be done by forbidding using top level type except for generic constraints -- of course it is too limiting.