Yes, it's a good idea, but your solution introduces virtual function calls
that could kill performance.

But most of D's methods are virtual. Nobody minds that opEquals or toString
are virtual and they're used a lot. Yes, it will be a performance hit for the
builtin implementation but would be the same for the programmer defined
implementations. If they're going to have to use a custom class anyway, why
not allow them to have the syntax to go with it?
Often in languages and compilers, you have to choose between flexibility and
speed, and that's a deicision for Walter.

Much better approch would be the following:
- Provide an "interface" that built-in AAs implement.
- Allow user-defined types to implement this interface.
- Allow these derived types to benefit from all the syntax sugar, used by
built-in containers.
- Allow users to replace built-in containers with user-defined ones.
(arguable)
Third point is necessary since there are still some tricks that can't be
used by programmer like 'in' operator in AAs.
This way containers could be replaced by user-defined types partially or
completely.

Why couldn't a person use "in" on a user-defined AA? According to the docs,
its overloadable with opIn (but no example on the page so maybe its not
supported anymore).