Walter Bright wrote:
Jacob Carlborg wrote:
It would be great if D could have categories/open classes and you could do something like this:

class A
{
    void foo () {}
}

class A
{
    void bar () {}
}

void main ()
{
    auto a = new A;
    a.foo;
    a.bar;
}

And it should of course work on classes you don't have access to the source code.

Setting aside the technical issues for the moment, isn't that exactly what inheritance is supposed to be good for?

Consider the above example is written as
> class A { int foo; }
> class B : A { int bar; }

The point is, that your code might need to associate additional data to class A. You could inherit from that class, and simply add the fields you need (in this case "bar"). (It's almost the same for virtual methods, just that virtual methods are like additional fields in the class' vtable, or something like this.)

Here's my arguments why inheritance isn't a general or elegant enough solution:

1. If you want to extend a class with inheritance, you need to have control about how the class is instantiated, so that you can insert your "new B();". That's trivial in Jacob's example code. But if the "new A();" line is hidden somewhere inside the foreign code, you obviously can't extend the class; the foreign code will give you only not-extended class instances. You can't cast them to B.

2. If A (or any other classes) has methods or properties, which have A as return type, you'll probably end up having to cast from A to B each time you want to use your extensions.

3. Inheritance works only once. There can't be two independent modules, which both extend the class A. At least not if these two modules want to use the same object instances. (Although the modules are independent, they both depend and use the module which provides class A, and might indirectly exchange object references through it. If both modules need to "extend" them, it won't work.)

The closest to achieve something that doesn't have the above mentioned problems, is to use a map with the object as key. For example:

> int[A] bar;

So whenever you need "bar" as additional field for A, you do an AA lookup with the object reference as key.

But this approach has performance and garbage collection problems, and it looks a bit ugly. The question is, is there a solution, which is both aesthetically and technically better?

Reply via email to