I'm trying to learn more about D object system (this is derived from a
discussion I've had in #D), I have problems fully understanding some of the
things the D docs say. This is a little Java program for reference:
// Java code
import java.util.*;
interface FooBar {}
class Foo implements FooBar {}
class Bar implements FooBar {}
public class test {
public static void main(String[] args) {
ArrayList<FooBar> things = new ArrayList<FooBar>();
things.add(new Bar());
things.add(new Foo());
for (FooBar thing : things)
System.out.println(thing.getClass());
}
}
/*
Output of the Java version:
class Bar
class Foo
*/
I have tried to translate it to D, and I have failed so far, this code compiles
and runs, but I'd like to see the original class names in the output:
// D code
import std.stdio;
interface FooBar {}
class Foo : FooBar {}
class Bar : FooBar {}
void main() {
FooBar[] things;
things ~= new Bar;
things ~= new Foo;
foreach (thing; things)
writefln(typeid(typeof(thing)));
}
/*
Output of the D version:
test.FooBar
test.FooBar
*/
As you can see in D I am not able yet to find the class of the objects inserted
into the 'things' array. Do you have suggestions? (I'd like to do this to sort
the 'things' array according to the class).
Bye and thank you,
bearophile

typeof() gives a static type of an object. But I was sure that
thing.classinfo.name should have referred to the dynamic type name.
Apparently it's not the case, it prints the same test.FooBar as in your
test.

typeof() gives a static type of an object. But I was sure that
thing.classinfo.name should have referred to the dynamic type name.
Apparently it's not the case, it prints the same test.FooBar as in your
test.

Thank you for your answer.
So the question here is: is the information I need present at runtime somewhere?
If the answer is true, then the problem is how to get it.
I think this page of the docs may be improved with few graphical drawings of
the data structures it talks about (with lines that show where the pointers
point to at runtime in a simple example); such images can probably give all or
most of the answers I was looking for:
http://www.digitalmars.com/d/1.0/phobos/object.html
Bye,
bearophile

typeof() gives a static type of an object. But I was sure that
thing.classinfo.name should have referred to the dynamic type name.
Apparently it's not the case, it prints the same test.FooBar as in your
test.

Thank you for your answer.
So the question here is: is the information I need present at runtime
somewhere?
If the answer is true, then the problem is how to get it.

obj.classinfo doesn't work the way you'd expect with an interface, but
it works when you've got an object:
writefln((cast(Object)thing).classinfo.name);
This does look ugly, though.

obj.classinfo doesn't work the way you'd expect with an interface, but
it works when you've got an object:
writefln((cast(Object)thing).classinfo.name);

Thanks for the tip! It seems like classinfo of an interface contains
information about the most derived interface implemented in an object:
interface a {}
interface aa : a {}
class A : aa {}
void main() {
writefln((cast(a) new A).classinfo.name);
}
prints "test.aa". Though this functionality is of questionable
usefulness (has anybody used it for something?) and besides it's broken:
interface a {}
interface aa : a {}
class A : a, aa {}
void main() {
writefln((cast(a) new A).classinfo.name);
}
prints "test.a" even though A implements the "aa" interface as well.

obj.classinfo doesn't work the way you'd expect with an interface, but
it works when you've got an object:
writefln((cast(Object)thing).classinfo.name);

Thanks for the tip! It seems like classinfo of an interface contains
information about the most derived interface implemented in an object:
interface a {}
interface aa : a {}
class A : aa {}
void main() {
writefln((cast(a) new A).classinfo.name);
}
prints "test.aa". Though this functionality is of questionable
usefulness (has anybody used it for something?) and besides it's broken:
interface a {}
interface aa : a {}
class A : a, aa {}
void main() {
writefln((cast(a) new A).classinfo.name);
}
prints "test.a" even though A implements the "aa" interface as well.

Since .classinfo is essentially a virtual call, and interface vtbls are
filled from the class's vtbl, it shouldn't in theory be terribly
difficult to change this. Of course, I'd have to check the dmd source to
be sure.

obj.classinfo doesn't work the way you'd expect with an interface, but
it works when you've got an object:
writefln((cast(Object)thing).classinfo.name);

Thanks for the tip! It seems like classinfo of an interface contains
information about the most derived interface implemented in an object:
interface a {}
interface aa : a {}
class A : aa {}
void main() {
writefln((cast(a) new A).classinfo.name);
}
prints "test.aa". Though this functionality is of questionable
usefulness (has anybody used it for something?) and besides it's broken:
interface a {}
interface aa : a {}
class A : a, aa {}
void main() {
writefln((cast(a) new A).classinfo.name);
}
prints "test.a" even though A implements the "aa" interface as well.

Since .classinfo is essentially a virtual call, and interface vtbls are
filled from the class's vtbl, it shouldn't in theory be terribly
difficult to change this. Of course, I'd have to check the dmd source to
be sure.

I'd say it's a bug. Classinfo is for runtime class, and runtime class
can never be an interface.

I'd say it's a bug. Classinfo is for runtime class, and runtime class
can never be an interface.

It seems all my questions in this newsgroup end with the discovery of another
possible (and often real) bug ;-]
If it's not a bug, then I think a nicer syntax may be appreciable. In such
thing Java may show some better syntax (well, better method name essentially,
so better API and not really better syntax).
Bye and thank you,
bearophile

Since .classinfo is essentially a virtual call, and interface vtbls are
filled from the class's vtbl, it shouldn't in theory be terribly
difficult to change this. Of course, I'd have to check the dmd source to
be sure.

I'd say it's a bug. Classinfo is for runtime class, and runtime class
can never be an interface.

Do all IUknown interface instances have classinfo member? That's not a bug
if they don't. That's the same reason why interfaces can't be casted to
Object.

IUnknown cannot be a D interface because it does not comply with D ABI.
IUnknown cannot have any .classinfo. Iunknown cannot be cast to
anything except by the means of QueryInterface(). You've chosen the
wrong example.
Only D interfaces can have .classinfo. You cannot instantiate a D
interface, only a class. Therefore whenever you get a reference it's
either null or refers to an instantiated *class* which definitely has
its one and only correct .classinfo.

Since .classinfo is essentially a virtual call, and interface vtbls are
filled from the class's vtbl, it shouldn't in theory be terribly
difficult to change this. Of course, I'd have to check the dmd source to
be sure.

I'd say it's a bug. Classinfo is for runtime class, and runtime class
can never be an interface.

Do all IUknown interface instances have classinfo member? That's not a bug
if they don't. That's the same reason why interfaces can't be casted to
Object.

IUnknown cannot be a D interface because it does not comply with D ABI.

My apologies. I didn't know that IUnknown were directly supported by a
compiler as a special case of a super-interface. Everything you say
seems to be relevant now.

it works when you've got an object:
writefln((cast(Object)thing).classinfo.name);

Thanks for the tip! It seems like classinfo of an interface contains
information about the most derived interface implemented in an object:
interface a {}
interface aa : a {}
class A : aa {}
void main() {
writefln((cast(a) new A).classinfo.name);
}
prints "test.aa". Though this functionality is of questionable
usefulness (has anybody used it for something?) and besides it's

Since .classinfo is essentially a virtual call, and interface vtbls are
filled from the class's vtbl, it shouldn't in theory be terribly
difficult to change this. Of course, I'd have to check the dmd source to
be sure.

I'd say it's a bug. Classinfo is for runtime class, and runtime class
can never be an interface.

Do all IUknown interface instances have classinfo member? That's not a bug
if they don't. That's the same reason why interfaces can't be casted to
Object.