Newbie: copy, assignment of class instances

Ali Çehreli acehreli at yahoo.com
Thu May 27 14:49:14 PDT 2010


bearophile wrote:
> Larry Luther:
> 
>> Ok, I've added -w to compilation commands and I've switched back to pure text.<
> 
> Good :-)
> 
> 
>> What am I missing?<
> 
> I have modified a bit your D code like this, to have something with a main() that runs:
> 
> 
> import std.c.stdio: puts;
> 
> class A {
>     int x, y;
> 
>     void copy(const A a) {
>         puts("A copy");
>         x = a.x;
>         y = a.y;
>     }
> }
> 
> class B : A {
>     int z;
> 
>     void copy(const B b) {
>         puts("B copy");
>         super.copy(b);
>         z = b.z;
>     }
> }
> 
> void main() {
>     A a1 = new A;
>     A a2 = new A;
> 
>     B b1 = new B;
>     B b2 = new B;
> 
>     a1.copy(a2); // should execute A.copy
>     a1.copy(b1); // should execute A.copy
>     b1.copy(b2); // should execute B.copy
>     b1.copy(a1); // should execute A.copy
> }
> 
> 
> 
> I have also translated your the code to Java, because sometimes Java designers are more "correct" thant D designers:
> 
> 
> class A {
>     int x, y;
> 
>     void mycopy(A a) {
>         System.out.println("A mycopy");
>         x = a.x;
>         y = a.y;
>     }
> }
> 
> class B extends A {
>     int z;
> 
>     void mycopy(B b) {
>         System.out.println("B mycopy");
>         super.mycopy(b);
>         z = b.z;
>     }
> 
>     public static void main(String[] args) {
>         A a1 = new A();
>         A a2 = new A();
> 
>         B b1 = new B();
>         B b2 = new B();
> 
>         a1.mycopy(a2); // should execute A.mycopy
>         a1.mycopy(b1); // should execute A.mycopy
>         b1.mycopy(b2); // should execute B.mycopy
>         b1.mycopy(a1); // should execute A.mycopy
>     }
> }
> 
> 
> The Java code compiles and runs with no errors, and prints:
> A mycopy
> A mycopy
> B mycopy
> A mycopy
> A mycopy
> 
> 
> But the D version is different. It seems you have found a small difference between Java and D that I didn't know about.
> 
> If I comment out the last line of the main() in the D code (b1.copy(a1);) and I compile the D code with -w it generates the warning I was talking about:
> 
> test.d(13): Error: class test.B test.A.copy(const const(A) a) is hidden by B
> 
> 
> If I leave that line uncommented then the compilation stops with a different error:
> 
> test.d(33): Error: function test.B.copy (const const(B) b) is not callable using argument types (A)
> test.d(33): Error: cannot implicitly convert expression (a1) of type test.A to const(B)
> 
> It seems in D the copy() of B replaces (hides) the copy() of A, even if no override is used. I don't know why D is designed this way, it can even be a design/implementation bug. But the presence of that warning suggests me this is expected, so it's probably just a difference between Java and D. If no one answers to this here then maybe later I will ask about this in the main D group.
> 
> Bye,
> bearophile

For what it's worth, here is a code that uses 'dup' instead of 'copy'. I 
know this is not the same thing; but I find this more intuitive:

import std.stdio;
import std.string;

class A
{
     int x, y;

     this(int x, int y)
     {
         this.x = x;
         this.y = y;
     }

     A dup() const
     {
         writeln("A copy");
         return new A(x, y);
     }

     override string toString() const
     {
         return format("A(%s,%s)", x, y);
     }
}

class B : A
{
     int z;

     this(int x, int y, int z)
     {
         super(x, y);
         this.z = z;
     }

     override B dup() const
     {
         writeln("B copy");
         return new B(x, y, z);
     }

     override string toString() const
     {
         return format("B(%s,%s,%s)", x, y, z);
     }
}

void main() {
     A a1 = new A(1, 1);
     A a2 = new A(2, 2);
     B b1 = new B(11, 11, 11);
     B b2 = new B(22, 22, 22);

     a1 = a2.dup;
     assert((a1.x == 2) && (a1.y == 2));

     a1 = b1.dup;
     assert((a1.x == 11) && (a1.y == 11));
     assert(typeid(a1) == typeid(B));      // <-- personality change

     b1 = b2.dup;
     assert((b1.x == 22) && (b1.y == 22) && (b1.z == 22));

     // b1 = a1.dup; // <-- ERROR because not all As are Bs;
     //                           but as we know that a1 is
     //                           actually a B at this point;
     //                           we can down cast:
     assert(cast(B)a1 !is null);
     b1 = (cast(B)a1).dup;
     assert((b1.x == 11) && (b1.y == 11) && (b1.z == 11));

     writeln(a1);
     writeln(a2);
     writeln(b1);
     writeln(b2);
}

Ali


More information about the Digitalmars-d-learn mailing list