Newbie: copy, assignment of class instances

bearophile bearophileHUGS at lycos.com
Thu May 20 14:56:54 PDT 2010


Larry Luther:

>  B foo = new B,
>  B bar = new B;

This is not valid D code, you have to use something like:

B foo = new B;
B bar = new B;


I suggest you to actually try to compile and run your little test programs. If you compile this:


class A {
    int x, y;

    void copy(A a) {
        x = a.x;
        y = a.y;
    }
}

class B : A { // line 10
    int z;

    void copy(B b) {
        super.copy(b);
        z = b.z;
    }

}

void main() {
    B foo = new B;
    B bar = new B;
}


You get this (badly written) error:
test.d(10): Error: class test2.B test2.A.copy(A a) is hidden by B



This works:


import std.stdio: writeln;
import std.string: format;


template ExceptionTemplate() {
    this() {
        super(this.classinfo.name);
    }

    this(string msg) {
        super(this.classinfo.name ~ ": " ~ msg);
    }
}


class ArgumentException: Exception {
    mixin ExceptionTemplate;
}


class A {
    int x, y;

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

    void copyFrom(Object other) {
        auto o = cast(typeof(this))other;
        if (o is null)
            throw new ArgumentException("Some message here...");
        x = o.x;
        y = o.y;
    }

    override string toString() {
        return format("A(%d, %d)", this.x, this.y);
    }
}

class B : A {
    int z;

    this(int xx, int yy, int zz) {
        super(xx, yy);
        this.z = zz;
    }

    override void copyFrom(Object other) {
        auto o = cast(typeof(this))other;
        if (o is null)
            throw new Exception("..."); // use a more specific exception here
        super.copyFrom(other);
        z = o.z;
    }

    override string toString() {
        return format("B(%d, %d, %d)", this.x, this.y, this.z);
    }
}

void main() {
    B foo = new B(1, 2, 3);
    B bar = new B(4, 5, 6);

    writeln("foo = ", foo);
    writeln("bar = ", bar);

    foo.copyFrom(bar);

    writeln("foo = ", foo);
    writeln("bar = ", bar);
}


Output:
foo = B(1, 2, 3)
bar = B(4, 5, 6)
foo = B(4, 5, 6)
bar = B(4, 5, 6)




An alternative implementation:


import std.stdio: writeln;
import std.string: format;


template ExceptionTemplate() {
    this() {
        super(this.classinfo.name);
    }

    this(string msg) {
        super(this.classinfo.name ~ ": " ~ msg);
    }
}


class ArgumentException: Exception {
    mixin ExceptionTemplate;
}


class A {
    int x, y;

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

    void copyFrom(typeof(this) other) {
        x = other.x;
        y = other.y;
    }

    override string toString() {
        return format("A(%d, %d)", this.x, this.y);
    }
}


class B : A {
    int z;

    this(int xx, int yy, int zz) {
        super(xx, yy);
        this.z = zz;
    }

    override void copyFrom(typeof(super) other) {
        auto o = cast(typeof(this))other;
        if (o is null)
            throw new ArgumentException("Some message here...");
        super.copyFrom(other);
        z = o.z;
    }

    override string toString() {
        return format("B(%d, %d, %d)", this.x, this.y, this.z);
    }
}


void main() {
    B foo = new B(1, 2, 3);
    B bar = new B(4, 5, 6);

    writeln("foo = ", foo);
    writeln("bar = ", bar);

    foo.copyFrom(bar);

    writeln("foo = ", foo);
    writeln("bar = ", bar);
}


In other languages an operator as "isa" replaces the less nice looking dynamic cast followed by null test.

Bye,
bearophile


More information about the Digitalmars-d-learn mailing list