digitalmars.D.learn - Like getClass()
- bearophile (41/41) Sep 27 2008 I'm trying to learn more about D object system (this is derived from a d...
- Sergey Gromov (6/23) Sep 27 2008 typeof() gives a static type of an object. But I was sure that
- bearophile (8/12) Sep 27 2008 Thank you for your answer.
- torhu (5/14) Sep 27 2008 obj.classinfo doesn't work the way you'd expect with an interface, but
- bearophile (6/8) Sep 27 2008 It works, thank you very much. Now I'll try to use it for the original p...
- bearophile (62/62) Sep 27 2008 I have solved my original problem :-) I show here the code for reference...
- Sergey Gromov (19/23) Sep 27 2008 Thanks for the tip! It seems like classinfo of an interface contains
- Christopher Wright (5/33) Sep 27 2008 Since .classinfo is essentially a virtual call, and interface vtbls are
- Sergey Gromov (4/38) Sep 27 2008 I'd say it's a bug. Classinfo is for runtime class, and runtime class
- bearophile (5/7) Sep 27 2008 It seems all my questions in this newsgroup end with the discovery of an...
- Denis Koroskin (5/45) Sep 28 2008 Do all IUknown interface instances have classinfo member? That's not a b...
- Sergey Gromov (10/26) Sep 28 2008 IUnknown cannot be a D interface because it does not comply with D ABI. ...
- Sergey Gromov (5/25) Oct 02 2008 My apologies. I didn't know that IUnknown were directly supported by a
- Tim M (76/107) Oct 17 2008 Did you ever figure out what you were trying to solve. typeof is evaluat...
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
Sep 27 2008
Sat, 27 Sep 2008 12:15:07 -0400, bearophile wrote:// 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 */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.
Sep 27 2008
Sergey Gromov: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
Sep 27 2008
bearophile wrote:Sergey Gromov: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.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.
Sep 27 2008
torhu:writefln((cast(Object)thing).classinfo.name);It works, thank you very much. Now I'll try to use it for the original purposes...... I'll have to work some more. I'll show here the results if I finish.This does look ugly, though.Well, better ugly than not having any way to solve the problem :-) Bye, bearophile
Sep 27 2008
I have solved my original problem :-) I show here the code for reference: This is the original Python code, that sorts a python list (array) of objects according to their class: class Circle: def __init__(self, x, y, radius): self.x = x self.y = y self.radius = radius def draw(self): print "Drawing Circle at (%s,%s) with radius %s" % (self.x, self.y, self.radius) class Square: def __init__(self, x, y, width): self.x = x self.y = y self.width = width def draw(self): print "Drawing Square at (%s,%s) with width %s" % (self.x, self.y, self.width) if __name__ == "__main__": shapes = [Circle(1,1,5), Square(2,4,3), Circle(3,3,7), Square(4,2,4)] shapes.sort(key=lambda s: order.index(s.__class__)) for shape in shapes: shape.draw() This is my best D translation so far, I am happy enough: import std.stdio: writefln; import d.func: sort, findPos; interface Shape { void draw(); } class Circle : Shape { float x, y, radius; this(float x, float y, float radius) { this.x = x; this.y = y; this.radius = radius; } void draw() { writefln("Drawing Circle at (%s,%s) with radius %s", x, y, radius); } } class Square : Shape { float x, y, width; this(float x, float y, float width) { this.x = x; this.y = y; this.width = width; } void draw() { writefln("Drawing Square at (%s,%s) with width %s", x, y, width); } } void main() { auto order = [Circle.classinfo, Square.classinfo]; // the order in which to draw the shapes auto shapes = [cast(Shape)(new Circle(1,1,5)), new Square(2,4,3), new Circle(3,3,7), new Square(4,2,4)]; shapes.sort((Shape s){ return findPos((cast(Object)s).classinfo, order); }); foreach (shape; shapes) shape.draw(); } It uses sort() and findPos(), but similar functions are probably present in Tango too, the first sorts an array according to a key function, and the second gives the index of an item into an iterable or -1 if absent. If the 'order' array becomes too much long it can of course be replaced by an associative array, that gives a faster lookup. Bye, bearophile
Sep 27 2008
Sat, 27 Sep 2008 19:50:18 +0200, torhu wrote: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.
Sep 27 2008
Sergey Gromov wrote:Sat, 27 Sep 2008 19:50:18 +0200, torhu wrote: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.
Sep 27 2008
Sat, 27 Sep 2008 19:21:56 -0400, Christopher Wright wrote:Sergey Gromov wrote:I'd say it's a bug. Classinfo is for runtime class, and runtime class can never be an interface.Sat, 27 Sep 2008 19:50:18 +0200, torhu wrote: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.
Sep 27 2008
Sergey Gromov: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
Sep 27 2008
On Sun, 28 Sep 2008 04:42:15 +0400, Sergey Gromov <snake.scaly gmail.com> wrote:Sat, 27 Sep 2008 19:21:56 -0400, Christopher Wright wrote: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.Sergey Gromov wrote:I'd say it's a bug. Classinfo is for runtime class, and runtime class can never be an interface.Sat, 27 Sep 2008 19:50:18 +0200, torhu wrote:butobj.classinfo doesn't work the way you'd expect with an interface,broken: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'sinterface 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.
Sep 28 2008
Mon, 29 Sep 2008 01:12:45 +0400, Denis Koroskin wrote:On Sun, 28 Sep 2008 04:42:15 +0400, Sergey Gromov <snake.scaly gmail.com> wrote: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.Sat, 27 Sep 2008 19:21:56 -0400, Christopher Wright wrote: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.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.
Sep 28 2008
Mon, 29 Sep 2008 03:02:58 +0400, Sergey Gromov wrote:Mon, 29 Sep 2008 01:12:45 +0400, Denis Koroskin wrote: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.On Sun, 28 Sep 2008 04:42:15 +0400, Sergey Gromov <snake.scaly gmail.com> wrote:IUnknown cannot be a D interface because it does not comply with D ABI.Sat, 27 Sep 2008 19:21:56 -0400, Christopher Wright wrote: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.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.
Oct 02 2008
Did you ever figure out what you were trying to solve. typeof is evaluated at compile time so not very useful. If it helps you or anyone else reading this some sample code you may find usefull: module test; import tango.io.Stdout; Object dupClass(Object o) { Object newObj = o.classinfo.create; return newObj; } class Animal { this(char[] name) { this.name = name; } this() { // } public char[] name; char[] kind() { return "animal"; } } class Dog : Animal { this(char[] name) { super(name); } this() { super(); } char[] kind() { return "Dog"; } } class Cat : Animal { this(char[] name) { super(name); } this() { super(); } char[] kind() { return "Cat"; } } int main(char[][] args) { Animal[] animals; Dog dog = new Dog("Scooby"); Cat cat = new Cat("Garfield"); /* create a new object of the same class as dog */ animals ~= cast(Animal) dupClass(dog); /* new dog needs a name */ animals[0].name = "Lassy"; /* add the others to the array */ animals ~= dog; animals ~= cat; foreach(Animal anim; animals) { Stdout(anim.kind~" : "~anim.name).newline; } return 0; } On Fri, 03 Oct 2008 14:44:11 +1300, Sergey Gromov <snake.scaly gmail.com> wrote:Mon, 29 Sep 2008 03:02:58 +0400, Sergey Gromov wrote:Mon, 29 Sep 2008 01:12:45 +0400, Denis Koroskin wrote: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.On Sun, 28 Sep 2008 04:42:15 +0400, Sergey Gromov<snake.scaly gmail.com>wrote:vtbls areSat, 27 Sep 2008 19:21:56 -0400, Christopher Wright wrote:Since .classinfo is essentially a virtual call, and interfacesource tofilled from the class's vtbl, it shouldn't in theory be terribly difficult to change this. Of course, I'd have to check the dmdclassbe sure.I'd say it's a bug. Classinfo is for runtime class, and runtimea bugcan never be an interface.Do all IUknown interface instances have classinfo member? That's notif they don't. That's the same reason why interfaces can't be castedtoObject.IUnknown cannot be a D interface because it does not comply with D ABI.
Oct 17 2008