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