class A : B
{
   B b;
alias b this; //Error: super type (B) always hides "aliasthised" type B because base classes should be processed before alias this types.
}


This isn't an error? Just because A inherits B doesn't mean that the alias is wrong?

e.g., If you have

class A1 { B b; alias b this; }

and

class A2 : B { B b; alias b this; }

A2 is just A1 in all forms. Whats great about it is that it allows easy composition patterns. (that is, A1 has essentially implemented B through the alias)

e.g., we can reassign b to a different behavior without having to write any boil code. It allows one to decompose classes and their implementations in a natural way.

Of course, it would require the alias this to be processed before the base class.

I think that it would be worth the alias to override the inheritance because it makes things easier:


class A : BBB { BB b; alias b this; }

If BBB and BB are related in some complex way the compiler has to deduce this. e.g.,

class BBB : Q!B { }

where Q!B is some template that is a superclass of B.

But if the alias is processed first, it won't matter.


* Regarding the lookup, opDispatch shouldn't come before alias this, or should come before base class lookup. Essentially alias this is subtyping so it should enjoy similar privileges to base classes. A different way to look at it is opDispatch is a "last resort" lookup mechanism, just one step above the UFCS lowering.

I agree with this suggestion, however it breaks an existing code. opDispatch shouldn't come before base type lookup, because it will hide basic methods like toString. opDispatch may come after alias this lookup, however it will fundamentally change program behaviour.

Why can't you simply have opDispatch call the base class lookup if all others fail?

It seems to me that one should have

alias this > opDispatch > class > base class(es)

But each one has a fall through mechanism.

e.g., if someone overrides toString in opDispatch it will call their function, if not, it gets passed to the bass class tostring.

Why should it work this way? Because alias this and opDispatch are user defined. The user "knows" why they are doing and the compiler doesn't get in the way by preventing them from doing things they want to do.

The compiler essentially fixes up all the missing connections that it can but never forcing connections the user may not want.


Basically all one needs is something like

bool opAliasDispatch(...)
{
   if (...) { ... return true; } // tries to dispatch
   return false;
}


bool opDispatch(...)
{
   if (...) { ... return true; } // tries to dispatch
   return false;
}

bool opClassDispatch(...)
{
   if (...) { ... return true; } // tries to dispatch
   return false;
}

bool opBaseDispatch(...)
{
   if (...) { ... return true; } // tries to dispatch
   return false;
}

Then a master dispatcher is

bool opMasterDispatch(...)
{
return opAliasDispatch(...) || opDispatch(...) || opClassDispatch(...) || opBaseDispatch(...);
}



This makes it easier to add new dispatchers in the future, etc.

Also, if you are worried about backwards compatibility, just create a command line switch to select one method over another. Easy and it doesn't force everyone to be stuck with a suboptimal solution just for "backwards compatibility"(which is the scourge of humanity... We have to move forward, not be stuck in the past!!!).

Reply via email to