Thread overview
how to make new C return other static type than C
Dec 09, 2012
deed
Dec 09, 2012
Ali Çehreli
Dec 09, 2012
Adam D. Ruppe
Dec 09, 2012
deed
Dec 10, 2012
Ali Çehreli
December 09, 2012
interface I
{
    void setX(int x);
    int getX();
}

class C : I
{
    int x, y;

    void setX(int x) { this.x = x; }
    int getX()       { return x;   }
    void setY(int y) { this.y = y  }
    int getY()       { return y;   }
}


void main()
{
    auto obj = new C; // Want new C to instantiate obj with static type I.
    obj.setX(3);      // Ok, sets x to 3.
    obj.getY();       // Error, not specified in the interface.
}

- Is it possible to enforce, from within the class, a certain static interface type or ancestor type when instantiating with new? If so, how is it done?
- Also, is it possible for a class to implement multiple interfaces and choose static type among them when instantiated, based on static class state or arguments passed to the constructor?
December 09, 2012
On 12/09/2012 10:23 AM, deed wrote:
> interface I
> {
> void setX(int x);
> int getX();
> }
>
> class C : I
> {
> int x, y;
>
> void setX(int x) { this.x = x; }
> int getX() { return x; }
> void setY(int y) { this.y = y }
> int getY() { return y; }
> }
>
>
> void main()
> {
> auto obj = new C; // Want new C to instantiate obj with static type I.
> obj.setX(3); // Ok, sets x to 3.
> obj.getY(); // Error, not specified in the interface.
> }

new always returns an object of the actual type the programmer requested. It is up to the programmer what interface the object needs to be used with:

    C obj = new C;

Now the code works because getY() is being called on a C, which does have the definition of that function.

> - Is it possible to enforce, from within the class, a certain static
> interface type or ancestor type when instantiating with new? If so, how
> is it done?

Not possible.

> - Also, is it possible for a class to implement multiple interfaces and
> choose static type among them when instantiated, based on static class
> state or arguments passed to the constructor?

Again, it is always the same type of object. That object can be used by its many interfaces.

Ali

December 09, 2012
On Sunday, 9 December 2012 at 18:23:15 UTC, deed wrote:
> - Is it possible to enforce, from within the class, a certain static interface type or ancestor type when instantiating with new? If so, how is it done?

No, but you could make the constructor private so new doesn't work on it at all, and then use a factory function.

    static I make() { return new C(); }
    private this() {}

    auto obj = new C; // won't compile
    auto obj2 = C.make(); // works, obj2 static type is I

The make function could be a template or whatever and change the return type that way.


And, of course, don't forget

I obj = new C();

will always type obj as the interface.
December 09, 2012
Thanks for your replies. How about this:

interface I {}

interface I1 : I
{
    void setx(int x);
    int getx();
    int getSum();
}

interface I2 : I
{
    void sety(int y);
    int gety();
    int getSum();
}

class Impl : I1, I2
{
    int x, y;

    void setx(int x)   { this.x = x;   }
    int getx()         { return x;     }
    void sety(int y)   { this.y = y;   }
    int gety()         { return y;     }
    int getSum()       { return x + y; }
}

class C
{
    I1 i1;
    I2 i2;
    I currentInterface;

    this()
    {
        i1 = new Impl;    // static type I1
        i2 = csat(I2)i1;  // try to refer to same object through i2
        currentInterface = i1;
    }

    void switchInterface()   // Could be private and called depending on
                             // internal state
    {
        if (currentInterface == i1) { currentInterface = i2; }
        else                        { currentInterface = i1; }
    }

    /* Direct all method calls to the current interface...
       Perhaps opDispatch?
    */
}

void main()
{
    auto c = new C;
    c.setx(5);       // Should set x to 5 through i1
    c.getSum();      // Should return 5. (5 + 0)
    c.sety(3);       // Should not be possible
    c.switchInterface()   // currentInterface is now i2
    c.setx(10);      // Should not be possible
    c.sety(3);       // Should set y to 8 through i2
    c.getSum();      // Should return 8. (5 + 3)
}


- Could this be possible?
- Will i1 and i2 expose different interfaces to the same object?
- How can a method call on an object be directed to an internal object/interface?
December 10, 2012
On 12/09/2012 12:02 PM, deed wrote:
> void main()
> {
> auto c = new C;

D is a strongly statically typed language. The type of c is C, period. The compiler will compile the following lines of code all under that observation.

> c.setx(5); // Should set x to 5 through i1
> c.getSum(); // Should return 5. (5 + 0)
> c.sety(3); // Should not be possible
> c.switchInterface() // currentInterface is now i2

The compiler cannot analyze the implementation of switchInterface(). c is still a C.

> c.setx(10); // Should not be possible
> c.sety(3); // Should set y to 8 through i2
> c.getSum(); // Should return 8. (5 + 3)
> }
>
>
> - Could this be possible?

Not as you have shown.

> - Will i1 and i2 expose different interfaces to the same object?

Yes but it looks like they are not helping with what you are trying to achieve.

> - How can a method call on an object be directed to an internal
> object/interface?

Sometimes explicitly:

class C
{
    Member m;

    void foo()
    {
        m.foo();
    }
}

Sometimes automatically by alias this:

class C
{
    Member m;

    alias m this;
}

There must be other more suitable methods depending on the situation.

Ali