www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - how to make new C return other static type than C

reply "deed" <none none.none> writes:
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?
Dec 09 2012
next sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
Dec 09 2012
prev sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
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.
Dec 09 2012
parent reply "deed" <none none.none> writes:
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?
Dec 09 2012
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
Dec 09 2012