digitalmars.D - Getting derived classes
- dsimcha (5/5) Oct 16 2008 I know that, in std.traits, there's a template that spits out all base c...
- Andrei Alexandrescu (5/10) Oct 16 2008 That's not possible in general because in D the derived classes form an
- dsimcha (6/16) Oct 16 2008 Not quite sure I understand why this has to be the case. Somewhere in t...
- Denis Koroskin (5/30) Oct 16 2008 How do you get a list of all classes that derive from Object?
- Jason House (3/25) Oct 16 2008 There are many things hiding somewhere in the docs are many things that ...
- Sean Kelly (24/41) Oct 16 2008 I think the actual implementation of this is somewhat different. Rather...
- Jason House (2/51) Oct 17 2008 The compiler could be smarter than that, but isn't. I too was tricked by...
- Ary Borenszweig (2/18) Oct 17 2008
- Steven Schveighoffer (4/20) Oct 17 2008 Not at compile time, only at link time. You can't compile code at link
- Ary Borenszweig (8/31) Oct 17 2008 I still don't understand why you can't do this at compile time, assuming...
- Steven Schveighoffer (22/49) Oct 17 2008 Let's say this feature theoretically existed. Here's an example usage:
- Andrei Alexandrescu (9/60) Oct 17 2008 s/below/above/
- Sean Kelly (7/11) Oct 17 2008 Much of it is even exposed, just not in a convenient manner. A list of
- Steven Schveighoffer (4/14) Oct 17 2008 Sure, but what do you do with that graph ;) Calling methods/ctors is no...
- Christopher Wright (35/50) Nov 01 2008 Parameterless constructors are easy. Other than that, you can't be
- Bruno Medeiros (18/48) Oct 21 2008 It would be possible for the compiler to determine subtypes, if, just
- Robert Fraser (5/7) Oct 21 2008 The main use case I can see is a plugin solution. For example,
- BLS (6/22) Nov 01 2008 -> Jacha Wetzel
- BCS (4/10) Oct 17 2008 Via DLL/SO's, a derived class can be /written/ after the program that it...
- Bill Baxter (5/15) Oct 17 2008 I wonder what Object.Factory does when you try to make a class from a
- BCS (3/26) Oct 17 2008 it might work by hiding a static this function that registries the class...
- Jarrett Billingsley (2/5) Oct 17 2008 I think you've guessed correctly. DLLs, in general, are next to useless...
- Don (4/12) Oct 20 2008 Rather:
I know that, in std.traits, there's a template that spits out all base classes for a given class. Based on reading the source, it seems to work based on a rather interesting use case for is expressions. Is there any equivalent way to do the opposite: For any given position in a class hierarchy, to get a tuple of all possible descendants?
Oct 16 2008
dsimcha wrote:I know that, in std.traits, there's a template that spits out all base classes for a given class. Based on reading the source, it seems to work based on a rather interesting use case for is expressions. Is there any equivalent way to do the opposite: For any given position in a class hierarchy, to get a tuple of all possible descendants?That's not possible in general because in D the derived classes form an open set. I guess it could be done at runtime via reflection (not implemented afaik), but not at compile time. Andrei
Oct 16 2008
== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s articledsimcha wrote:Not quite sure I understand why this has to be the case. Somewhere in the docs, Walter explicitly says that, since D knows about the whole class tree, the compiler can figure out which functions in a hierarchy can be made non-virtual. If this is the case, why is the compiler not able to know about the whole class tree for purposes of creating lists of derived classes?I know that, in std.traits, there's a template that spits out all base classes for a given class. Based on reading the source, it seems to work based on a rather interesting use case for is expressions. Is there any equivalent way to do the opposite: For any given position in a class hierarchy, to get a tuple of all possible descendants?That's not possible in general because in D the derived classes form an open set. I guess it could be done at runtime via reflection (not implemented afaik), but not at compile time. Andrei
Oct 16 2008
dsimcha <dsimcha yahoo.com> писал(а) в своём письме Fri, 17 Oct 2008 06:18:34 +0400:== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s articleHow do you get a list of all classes that derive from Object? I might write one, too! Imagine we compile the source separately and then link obj files together.dsimcha wrote:Not quite sure I understand why this has to be the case. Somewhere in the docs, Walter explicitly says that, since D knows about the whole class tree, the compiler can figure out which functions in a hierarchy can be made non-virtual. If this is the case, why is the compiler not able to know about the whole class tree for purposes of creating lists of derived classes?I know that, in std.traits, there's a template that spits out allbase classesfor a given class. Based on reading the source, it seems to workbased on arather interesting use case for is expressions. Is there anyequivalent wayto do the opposite: For any given position in a class hierarchy, toget atuple of all possible descendants?That's not possible in general because in D the derived classes form an open set. I guess it could be done at runtime via reflection (not implemented afaik), but not at compile time. Andrei
Oct 16 2008
dsimcha wrote:== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s articleThere are many things hiding somewhere in the docs are many things that are not implemented :)dsimcha wrote:Not quite sure I understand why this has to be the case. Somewhere in the docs, Walter explicitly says that, since D knows about the whole class tree, the compiler can figure out which functions in a hierarchy can be made non-virtual. If this is the case, why is the compiler not able to know about the whole class tree for purposes of creating lists of derived classes?I know that, in std.traits, there's a template that spits out all base classes for a given class. Based on reading the source, it seems to work based on a rather interesting use case for is expressions. Is there any equivalent way to do the opposite: For any given position in a class hierarchy, to get a tuple of all possible descendants?That's not possible in general because in D the derived classes form an open set. I guess it could be done at runtime via reflection (not implemented afaik), but not at compile time. Andrei
Oct 16 2008
dsimcha wrote:== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s articleI think the actual implementation of this is somewhat different. Rather than relying on knowledge of the entire class tree, the compiler simply has to know what type a particular function is being called on. For example: class C { void fn() {} } void main() { auto c = new C; c.fn(); } Here, the compiler knows that it's dealing with an instance of C rather than a possibly unknown derived class so it can call fn() directly rather than going through the vtbl. However: void callFn( C c ) { c.fn(); } Here, the compiler doesn't know what the underlying type is so it must go through the vtbl. Seandsimcha wrote:Not quite sure I understand why this has to be the case. Somewhere in the docs, Walter explicitly says that, since D knows about the whole class tree, the compiler can figure out which functions in a hierarchy can be made non-virtual. If this is the case, why is the compiler not able to know about the whole class tree for purposes of creating lists of derived classes?I know that, in std.traits, there's a template that spits out all base classes for a given class. Based on reading the source, it seems to work based on a rather interesting use case for is expressions. Is there any equivalent way to do the opposite: For any given position in a class hierarchy, to get a tuple of all possible descendants?That's not possible in general because in D the derived classes form an open set. I guess it could be done at runtime via reflection (not implemented afaik), but not at compile time. Andrei
Oct 16 2008
Sean Kelly Wrote:dsimcha wrote:The compiler could be smarter than that, but isn't. I too was tricked by the same bit of D documentation. Avoiding virtual calls can be a significant speed gain. I have final functions throughout my code because gdc was too stupid to recognize they could be.== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s articleI think the actual implementation of this is somewhat different. Rather than relying on knowledge of the entire class tree, the compiler simply has to know what type a particular function is being called on. For example: class C { void fn() {} } void main() { auto c = new C; c.fn(); } Here, the compiler knows that it's dealing with an instance of C rather than a possibly unknown derived class so it can call fn() directly rather than going through the vtbl. However: void callFn( C c ) { c.fn(); } Here, the compiler doesn't know what the underlying type is so it must go through the vtbl. Seandsimcha wrote:Not quite sure I understand why this has to be the case. Somewhere in the docs, Walter explicitly says that, since D knows about the whole class tree, the compiler can figure out which functions in a hierarchy can be made non-virtual. If this is the case, why is the compiler not able to know about the whole class tree for purposes of creating lists of derived classes?I know that, in std.traits, there's a template that spits out all base classes for a given class. Based on reading the source, it seems to work based on a rather interesting use case for is expressions. Is there any equivalent way to do the opposite: For any given position in a class hierarchy, to get a tuple of all possible descendants?That's not possible in general because in D the derived classes form an open set. I guess it could be done at runtime via reflection (not implemented afaik), but not at compile time. Andrei
Oct 17 2008
Andrei Alexandrescu escribió:dsimcha wrote:But for a given set of modules, the hierarchy is finite and known.I know that, in std.traits, there's a template that spits out all base classes for a given class. Based on reading the source, it seems to work based on a rather interesting use case for is expressions. Is there any equivalent way to do the opposite: For any given position in a class hierarchy, to get a tuple of all possible descendants?That's not possible in general because in D the derived classes form an open set. I guess it could be done at runtime via reflection (not implemented afaik), but not at compile time.Andrei
Oct 17 2008
"Ary Borenszweig" wroteAndrei Alexandrescu escribi:Not at compile time, only at link time. You can't compile code at link time. -Stevedsimcha wrote:But for a given set of modules, the hierarchy is finite and known.I know that, in std.traits, there's a template that spits out all base classes for a given class. Based on reading the source, it seems to work based on a rather interesting use case for is expressions. Is there any equivalent way to do the opposite: For any given position in a class hierarchy, to get a tuple of all possible descendants?That's not possible in general because in D the derived classes form an open set. I guess it could be done at runtime via reflection (not implemented afaik), but not at compile time.
Oct 17 2008
Steven Schveighoffer wrote:"Ary Borenszweig" wroteI still don't understand why you can't do this at compile time, assuming you have the source code for everything that you'll link into your executable. How is a class hierarchy different in D than in Java? Eclipse JDT's has a type hierarchy feature, and Bruno was going to implement it in Mrnmhrm, all based on what's defined in the modules (you can say, compilte-time). What's the problem?Andrei Alexandrescu escribi:Not at compile time, only at link time. You can't compile code at link time.dsimcha wrote:But for a given set of modules, the hierarchy is finite and known.I know that, in std.traits, there's a template that spits out all base classes for a given class. Based on reading the source, it seems to work based on a rather interesting use case for is expressions. Is there any equivalent way to do the opposite: For any given position in a class hierarchy, to get a tuple of all possible descendants?That's not possible in general because in D the derived classes form an open set. I guess it could be done at runtime via reflection (not implemented afaik), but not at compile time.-Steve
Oct 17 2008
"Ary Borenszweig" wroteSteven Schveighoffer wrote:Let's say this feature theoretically existed. Here's an example usage: class X { Tuple!(???) getAllDerivedTypes() { return std.getAllDerivedTypes!(X)();} } If you compile this module like: dmd -c X.d; At this point, how does the compiler know all the modules that will derive from X? D's compile-time reflection is generally limited to what is at or below a certain point in the hierarchy, not what has derived from it. If you wanted to do something at runtime, that is possible, you might even be able to do this today by looking at the global TypeInfo array. But you certainly cannot get a tuple of the derived classes at compile-time."Ary Borenszweig" wroteI still don't understand why you can't do this at compile time, assuming you have the source code for everything that you'll link into your executable.Andrei Alexandrescu escribi:Not at compile time, only at link time. You can't compile code at link time.dsimcha wrote:But for a given set of modules, the hierarchy is finite and known.I know that, in std.traits, there's a template that spits out all base classes for a given class. Based on reading the source, it seems to work based on a rather interesting use case for is expressions. Is there any equivalent way to do the opposite: For any given position in a class hierarchy, to get a tuple of all possible descendants?That's not possible in general because in D the derived classes form an open set. I guess it could be done at runtime via reflection (not implemented afaik), but not at compile time.How is a class hierarchy different in D than in Java? Eclipse JDT's has a type hierarchy feature, and Bruno was going to implement it in Mrnmhrm, all based on what's defined in the modules (you can say, compilte-time). What's the problem?Java has runtime reflection. D does not. You have to implement runtime reflection on top of compile time reflection (or so says Walter). There should be no problem if you want the information at runtime. But a Tuple is a compile-time entity. You can probably get the TypeInfos of the classes, but not really be able to do much, since D's runtime reflection capabilities are limited. -Steve
Oct 17 2008
Steven Schveighoffer wrote:"Ary Borenszweig" wroteWell explained.Steven Schveighoffer wrote:Let's say this feature theoretically existed. Here's an example usage: class X { Tuple!(???) getAllDerivedTypes() { return std.getAllDerivedTypes!(X)();} } If you compile this module like: dmd -c X.d; At this point, how does the compiler know all the modules that will derive from X?"Ary Borenszweig" wroteI still don't understand why you can't do this at compile time, assuming you have the source code for everything that you'll link into your executable.Andrei Alexandrescu escribi:Not at compile time, only at link time. You can't compile code at link time.dsimcha wrote:But for a given set of modules, the hierarchy is finite and known.I know that, in std.traits, there's a template that spits out all base classes for a given class. Based on reading the source, it seems to work based on a rather interesting use case for is expressions. Is there any equivalent way to do the opposite: For any given position in a class hierarchy, to get a tuple of all possible descendants?That's not possible in general because in D the derived classes form an open set. I guess it could be done at runtime via reflection (not implemented afaik), but not at compile time.D's compile-time reflection is generally limited to what is at or below a certain point in the hierarchy, not what has derived from it.s/below/above/If you wanted to do something at runtime, that is possible, you might even be able to do this today by looking at the global TypeInfo array. But you certainly cannot get a tuple of the derived classes at compile-time.I said so. All derived classes is, however, a case of runtime-available information that's not there during compilation. Anyhow, there's a start with the function static Object.factory(string). You give it a string, it gives you a newly-instanced object. So the information is there, it just needs exposing. AndreiHow is a class hierarchy different in D than in Java? Eclipse JDT's has a type hierarchy feature, and Bruno was going to implement it in Mrnmhrm, all based on what's defined in the modules (you can say, compilte-time). What's the problem?Java has runtime reflection. D does not. You have to implement runtime reflection on top of compile time reflection (or so says Walter).
Oct 17 2008
Andrei Alexandrescu wrote:Anyhow, there's a start with the function static Object.factory(string). You give it a string, it gives you a newly-instanced object. So the information is there, it just needs exposing.Much of it is even exposed, just not in a convenient manner. A list of classes is available via ModuleInfo, and ClassInfo provides a means of finding the ClassInfo instance of a class by name. From there it should be possible to obtain a list of parent classes, and so one could build a hierarchy graph with some work. Sean
Oct 17 2008
"Sean Kelly" wroteAndrei Alexandrescu wrote:Sure, but what do you do with that graph ;) Calling methods/ctors is not exactly easy with D currently. -SteveAnyhow, there's a start with the function static Object.factory(string). You give it a string, it gives you a newly-instanced object. So the information is there, it just needs exposing.Much of it is even exposed, just not in a convenient manner. A list of classes is available via ModuleInfo, and ClassInfo provides a means of finding the ClassInfo instance of a class by name. From there it should be possible to obtain a list of parent classes, and so one could build a hierarchy graph with some work.
Oct 17 2008
Steven Schveighoffer wrote:"Sean Kelly" wroteParameterless constructors are easy. Other than that, you can't be certain what expectations the constructor has, so it's a bit dangerous, but you can of course get around that with documentation and try/catch. Calling methods isn't so difficult, either, since most of the stuff you'll be able to do involves virtual methods from some known base class. Dunit uses runtime reflection to get all test fixtures and run them. It uses something like: ClassInfo[] derived(ClassInfo info) { ClassInfo[] derivedClasses; foreach (module; ModuleInfo) foreach (clazz; module.localClasses) { if (isDerived(clazz; info)) derivedClasses ~= clazz; } return derivedClasses; } // Only works for interfaces. bool isDerived(ClassInfo derived, ClassInfo base) { while (derived) { if (base is derived) return true; derived = derived.base; } } I did this because I was tired of the static ctor mixin / static singleton registration pattern. I used to have to do: class FooTests : TestFixture { // I already told you it's a test fixture! // You mean I have to tell you twice?! mixin (DunitTest); } Now I can skip the mixin.Andrei Alexandrescu wrote:Sure, but what do you do with that graph ;) Calling methods/ctors is not exactly easy with D currently. -SteveAnyhow, there's a start with the function static Object.factory(string). You give it a string, it gives you a newly-instanced object. So the information is there, it just needs exposing.Much of it is even exposed, just not in a convenient manner. A list of classes is available via ModuleInfo, and ClassInfo provides a means of finding the ClassInfo instance of a class by name. From there it should be possible to obtain a list of parent classes, and so one could build a hierarchy graph with some work.
Nov 01 2008
Ary Borenszweig wrote:Steven Schveighoffer wrote:It would be possible for the compiler to determine subtypes, if, just like an IDE or build tool, the compiler had a well structured concept of a project (ie, a set of source folders, libraries, included modules, etc.). But just because it is possible, doesn't mean it's desirable, and in fact, it isn't. It's senseless: Such code (ie, getting all derived types) would introduce an open-ended compile-time coupling, as a module using that functionality would depended on *every* other module of the project. And that makes such functionality compilable only in projects that compile into an executable (which is when the set of dependencies is finite). That is, you couldn't use that functionality in a library, which shows much of an inane idea it is. It's breaking an abstraction barrier. Getting that information at *runtime* might be sensible, but I'm not seeing much usefulness in that. -- Bruno Medeiros - Software Developer, MSc. in CS/E graduate http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D"Ary Borenszweig" wroteI still don't understand why you can't do this at compile time, assuming you have the source code for everything that you'll link into your executable. How is a class hierarchy different in D than in Java? Eclipse JDT's has a type hierarchy feature, and Bruno was going to implement it in Mrnmhrm, all based on what's defined in the modules (you can say, compilte-time). What's the problem?Andrei Alexandrescu escribi:Not at compile time, only at link time. You can't compile code at link time.dsimcha wrote:But for a given set of modules, the hierarchy is finite and known.I know that, in std.traits, there's a template that spits out all base classes for a given class. Based on reading the source, it seems to work based on a rather interesting use case for is expressions. Is there any equivalent way to do the opposite: For any given position in a class hierarchy, to get a tuple of all possible descendants?That's not possible in general because in D the derived classes form an open set. I guess it could be done at runtime via reflection (not implemented afaik), but not at compile time.
Oct 21 2008
Bruno Medeiros wrote:Getting that information at *runtime* might be sensible, but I'm not seeing much usefulness in that.The main use case I can see is a plugin solution. For example, automatically instantiate all classes that extend IPlugin or something. However, requiring a config file that includes the class name and maybe some metadata isn't too hard to do and is potentially more efficient.
Oct 21 2008
Andrei Alexandrescu schrieb:dsimcha wrote:-> Jacha Wetzel Here is a simple way of adding __traits based runtime reflection to D classes: http://mainia.de/classinfoex.d (requires DMD 2.004)I know that, in std.traits, there's a template that spits out all base classes for a given class. Based on reading the source, it seems to work based on a rather interesting use case for is expressions. Is there any equivalent way to do the opposite: For any given position in a class hierarchy, to get a tuple of all possible descendants?That's not possible in general because in D the derived classes form an open set. I guess it could be done at runtime via reflection (not implemented afaik), but not at compile time. Andrei
Nov 01 2008
Reply to dsimcha,I know that, in std.traits, there's a template that spits out all base classes for a given class. Based on reading the source, it seems to work based on a rather interesting use case for is expressions. Is there any equivalent way to do the opposite: For any given position in a class hierarchy, to get a tuple of all possible descendants?Via DLL/SO's, a derived class can be /written/ after the program that it will be used in is /compiled/. Because of that (and other less restrictive forms of that issue) The most general answer is; can't be done.
Oct 17 2008
On Sat, Oct 18, 2008 at 6:20 AM, BCS <ao pathlink.com> wrote:Reply to dsimcha,I wonder what Object.Factory does when you try to make a class from a DLL like that. I'm guessing it doesn't work. --bbI know that, in std.traits, there's a template that spits out all base classes for a given class. Based on reading the source, it seems to work based on a rather interesting use case for is expressions. Is there any equivalent way to do the opposite: For any given position in a class hierarchy, to get a tuple of all possible descendants?Via DLL/SO's, a derived class can be /written/ after the program that it will be used in is /compiled/. Because of that (and other less restrictive forms of that issue) The most general answer is; can't be done.
Oct 17 2008
Reply to Bill,On Sat, Oct 18, 2008 at 6:20 AM, BCS <ao pathlink.com> wrote:it might work by hiding a static this function that registries the class, from that, when the dll lodes the class is registered.Reply to dsimcha,I wonder what Object.Factory does when you try to make a class from a DLL like that. I'm guessing it doesn't work. --bbI know that, in std.traits, there's a template that spits out all base classes for a given class. Based on reading the source, it seems to work based on a rather interesting use case for is expressions. Is there any equivalent way to do the opposite: For any given position in a class hierarchy, to get a tuple of all possible descendants?Via DLL/SO's, a derived class can be /written/ after the program that it will be used in is /compiled/. Because of that (and other less restrictive forms of that issue) The most general answer is; can't be done.
Oct 17 2008
On Fri, Oct 17, 2008 at 5:34 PM, Bill Baxter <wbaxter gmail.com> wrote:I wonder what Object.Factory does when you try to make a class from a DLL like that. I'm guessing it doesn't work.I think you've guessed correctly. DLLs, in general, are next to useless with D.
Oct 17 2008
Jarrett Billingsley wrote:On Fri, Oct 17, 2008 at 5:34 PM, Bill Baxter <wbaxter gmail.com> wrote:Rather: A D app and a D DLL can only communicate via extern(C) interfaces. Or via COM. It's not great, but it isn't any worse than DLLs in C++.I wonder what Object.Factory does when you try to make a class from a DLL like that. I'm guessing it doesn't work.I think you've guessed correctly. DLLs, in general, are next to useless with D.
Oct 20 2008