www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - how can i use the derive-hierarchy at runtime for typechecking?

reply dennis luehring <dl.soluz gmx.net> writes:
is there a way to test at runtime if the type of an object is derived 
from another object type? maybe with the help of compiletime-reflection 
and additional information in the class?

class A{}
class B: A{}
class C: B{}

i need something like

B.type.is_derived_from( A.type ) ==> true
A.type.is_derived_from( C.type ) ==> false

B xx = new B;
B yy = new B;

xx.type == yy.type ==> true

is there an elegant way?

why do i need such stuff?
i use the normal D typechecking for the static part of my software
but i've got an GUI system with the ability to "construct" types
at runtime based on my static types (and i need a typesystem based on 
the class hierachy for it)

thx dennis
Sep 20 2007
parent reply Downs <default_357-line yahoo.de> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Just cast it.
If you have class A { } and class B : A { }
and A foo=new B;
then you can do cast(B) foo and it will be non-null.
On the other hand, if you do A bar=new A;
and you do cast(B) bar, it will be null.

Here's a little utility function for this
void ifIs(S, T)(S obj, void delegate(T) dg) {
  auto casted=cast(T) obj;
  if (casted) dg(casted);
}

Use it like thus

ifIs(foo, (B whee) { /* do stuff with whee */ });

Hope that answers your question.
 --downs/FeepingCreature
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFG8ugVpEPJRr05fBERAiazAKCn3BIgtWPuCPeONAgE4AZZZ5BPZwCgjwFh
GvztcB0FD5gA2U6sBA6pZsc=
=G05B
-----END PGP SIGNATURE-----
Sep 20 2007
parent reply Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Downs wrote:
 -----BEGIN PGP SIGNED MESSAGE-----
 Hash: SHA1
 
 Just cast it.
 If you have class A { } and class B : A { }
 and A foo=new B;
 then you can do cast(B) foo and it will be non-null.
 On the other hand, if you do A bar=new A;
 and you do cast(B) bar, it will be null.
 
 Here's a little utility function for this
 void ifIs(S, T)(S obj, void delegate(T) dg) {
   auto casted=cast(T) obj;
   if (casted) dg(casted);
 }
 
 Use it like thus
 
 ifIs(foo, (B whee) { /* do stuff with whee */ });
 

And thanks to an oft-forgotten feature, you could shrink that down a little further to just a one-liner: void ifIs (S, T) (S obj, void delegate(T) dg) { if (auto casted = cast(T) obj) dg(casted); } http://digitalmars.com/d/1.0/statement.html#IfStatement -- Chris Nicholson-Sauls
Sep 20 2007
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Chris Nicholson-Sauls" <ibisbasenji gmail.com> wrote in message 
news:fcupko$kh7$2 digitalmars.com...

 void ifIs (S, T) (S obj, void delegate(T) dg) {
   if (auto casted = cast(T) obj) dg(casted);
 }

Or you could skip Downs' confusing way of writing code entirely ( ;) ) and just use: if(auto b = cast(B)foo) { // do stuff with b }
Sep 20 2007
next sibling parent reply Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Jarrett Billingsley wrote:
 "Chris Nicholson-Sauls" <ibisbasenji gmail.com> wrote in message 
 news:fcupko$kh7$2 digitalmars.com...
 
 void ifIs (S, T) (S obj, void delegate(T) dg) {
   if (auto casted = cast(T) obj) dg(casted);
 }

Or you could skip Downs' confusing way of writing code entirely ( ;) ) and just use: if(auto b = cast(B)foo) { // do stuff with b }

Or we could add a new '?.' form for member access that becomes a nop on null references and just use: (cast(B) foo)?.doStuff(); Er.......... okay, that's just insane. -- Chris Nicholson-Sauls
Sep 20 2007
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Chris Nicholson-Sauls" <ibisbasenji gmail.com> wrote in message 
news:fcv1d1$vp6$1 digitalmars.com...
 Or we could add a new '?.' form for member access that becomes a nop on 
 null references and just use:
 (cast(B) foo)?.doStuff();

 Er.......... okay, that's just insane.

What do you think this is, Io?
Sep 20 2007
prev sibling next sibling parent reply dennis luehring <dl.soluz gmx.net> writes:
Jarrett Billingsley schrieb:
 "Chris Nicholson-Sauls" <ibisbasenji gmail.com> wrote in message 
 news:fcupko$kh7$2 digitalmars.com...
 
 void ifIs (S, T) (S obj, void delegate(T) dg) {
   if (auto casted = cast(T) obj) dg(casted);
 }

Or you could skip Downs' confusing way of writing code entirely ( ;) ) and just use: if(auto b = cast(B)foo) { // do stuff with b }

and how can i insert this test in my base-class to hide the type stuff class base { int base_bla; bool is_derived_from( base other ) { auto check = cast(typeof(this))other; return !( check is null ); // why can't i compile this // return ( auto check = cast(typeof(this))other ); } } class test: base { int test_bla; } class blub: test { int blub_bla; } the is_derived_from test is always true maybe because of the base type parameter in is_derived_from and the other thing i need to know(show) the derive-hierachy "the hole story" in my c++ project i use objects which represents the type of an object for example class car // real implementation { } class car_class // object-type of class car { car create_instance(); ... bool is_derived_from base_class[] derived_from_me(); base_class[] base_class_of(); } and many [whatever]_class objects in my known-types-pool for example: i can ask which "types" i know i can create real types of it i can ask for the derives/bases of an "type" i can test if an "type" is hierachical "compatible"=derived from with another "type" and just need to know my base-class interface for doing this ... all this is done by using my own decription.language (with derive ability) and an c++ code generator... i hope to find a better (more compiletime based) way to get the same features - i want to get rid of this generator stuff ciao dennis
Sep 20 2007
parent Regan Heath <regan netmail.co.nz> writes:
dennis luehring wrote:
 Jarrett Billingsley schrieb:
 "Chris Nicholson-Sauls" <ibisbasenji gmail.com> wrote in message 
 news:fcupko$kh7$2 digitalmars.com...

 void ifIs (S, T) (S obj, void delegate(T) dg) {
   if (auto casted = cast(T) obj) dg(casted);
 }

Or you could skip Downs' confusing way of writing code entirely ( ;) ) and just use: if(auto b = cast(B)foo) { // do stuff with b }

and how can i insert this test in my base-class to hide the type stuff class base { int base_bla; bool is_derived_from( base other ) { auto check = cast(typeof(this))other; return !( check is null ); // why can't i compile this

Because using 'auto' like this only works in an "if" statement. eg. if ( auto check = cast(typeof(this))other ) return true; return false;
     // return ( auto check = cast(typeof(this))other );
   }
 }
 
 class test: base
 {
   int test_bla;
 }
 
 class blub: test
 {
   int blub_bla;
 }
 
 the is_derived_from test is always true
 maybe because of the base type parameter in is_derived_from

writefln(typeof(this).stringof) shows "base" even when called on an object of type "test" or "blub". So, even if you say: test t = new test; blub b = new blub; if (t.is_derived_from(b)) {} //is 'test' derived from 'blub' you're really just asking if t is derived from "base", which it is (has to be to have the is_derived_from method - in this case) Regan
Sep 21 2007
prev sibling parent Downs <default_357-line yahoo.de> writes:
Jarrett Billingsley wrote:
 "Chris Nicholson-Sauls" <ibisbasenji gmail.com> wrote in message 
 news:fcupko$kh7$2 digitalmars.com...
 
 void ifIs (S, T) (S obj, void delegate(T) dg) {
   if (auto casted = cast(T) obj) dg(casted);
 }

Or you could skip Downs' confusing way of writing code entirely ( ;) ) and just use: if(auto b = cast(B)foo) { // do stuff with b }

:surprised: --downs, learning new stuff every day! :)
Sep 23 2007