0

Are there any system of classe reference in D? To be more accurate I look for the equivalent of the Delphi

TMyClassRef = class of TMyClass;

This would be used for a factory (just like in the Object but without using the class name):

// ideally
void AddNew(*TBaseClass APtr, /*?class_ref_type?*/ AClassType)
{
    *APtr = new AClassType;
}

Currently I do this:

void AddNew(*TBaseClass APtr)
{
    *APtr = new typeof(*APtr);
}

But the problem is that typeof() returns always TBaseClass and never a sub class of TBaseClass (when a sub class is passed as parameter). This is clearly a case where class references would be used in Delphi but the D language doesn't seem to have such a system.

sigod
  • 3,514
  • 2
  • 21
  • 44
babu67
  • 69
  • 7
  • Maybe this helps: http://forum.dlang.org/thread/CAEyOLyDZaL2QtwvwF9=ktig+LN95Cb-VY-2M4e0Dvq4=jWp1_w@mail.gmail.com – sigod Mar 08 '13 at 22:11
  • Take a look at compile-time parameters: http://ddili.org/ders/d.en/templates.html – sigod Mar 09 '13 at 10:31

2 Answers2

2

D has no class references in the Delphi way as far as I have understood Delphi concept. If you need to make a run-time decision about object construction, object.TypeInfo may help you.

You can retrieve TypeInfo for a variable via typeid construct:

import std.stdio;

class Base
{
    void f()
    {
        writeln("Base");
    }
}

class Descendant : Base
{
    override void f()
    {
        writeln("Descendant");
    }   
}

Base makeNew(Base other)
{
    // cast is needed because create() returns plain Object
    // we can be sure it is Base at least, though, because it was crated from Base
    return cast(Base)typeid(other).create();
}

void main()
{
    Descendant source = new Descendant;
    Base target = makeNew(source);
    // prints "Descendant"
    target.f();
}

Is this code sample similar to what you want?

D generally has a very clear differentiation between run-time actions and compile-time ones. typeof works on compile-time and thus can't query "real" class type in case of hierarchies.

sigod
  • 3,514
  • 2
  • 21
  • 44
Mihails Strasuns
  • 3,783
  • 1
  • 18
  • 21
  • your code sample is similar but in my case it cant work like this because I have no valid source yet...so ̉`typid(other)` triggers an AV. This is exactly what would a class reference help into... is there any other way to query the type id, so at the run-time, from an unitialized Object ? – babu67 Mar 08 '13 at 22:46
  • But if the object is unintialized, its runtime type is not known (i.e. it can be the base class or one of its descendants.) If you don't want to initialize the object just yet, you can carry the 'target information' in another variable. If you are unclear, I will post some code. – yaz Mar 09 '13 at 06:08
  • Or of course if all the information you need is available at compile time, you can use templates. – yaz Mar 09 '13 at 06:20
  • 1
    Generally, what @yaz has just said. Delphi seems to somewhat inter-connect compile-time world and rune-time, in somewhat weird way to my taste. If you will describe your use case, I am sure better solution can be found. D is very straightforward here - to use run-time TypeInfo you need existing object. If decision can be made without actually creating object, it should be done via templates. – Mihails Strasuns Mar 09 '13 at 07:31
2

Maybe I'm completely missing the idea in Delphi, but this seems to be what a templates are for:

import std.stdio;

class Parent {
    string inherited() {
        return "Hello from parent";
    }

    override string toString() {
        return "Hello from parent";
    }
}

class Child : Parent {
    override string toString() {
        return "Hello from child";
    }
}

void add(C, P)(P* ptr) {
    *ptr = new C;
}

void main() {
    Parent t;
    writeln(t); // prints null

    add!Child(&t);
    writeln(t); // prints Hello from child
    writeln(t.inherited()); // prints Hello from parent
}

This way you pass in the type you want to instantiate instead of an instantiated object of that type. This should generate compile errors if C is not a child of P in add().

Edit:

If you want to be more specific with add, you could do this:

void add(T : Parent)(Parent* ptr) {
    *ptr = new T;
}

To make things nicer, use an out parameter to be more idiomatic:

void add(T : Parent)(out Parent ptr) {
    ptr = new T;
}
void main() {
    Parent p;
    add!Child(p);
}
beatgammit
  • 19,817
  • 19
  • 86
  • 129
  • Thx this perfectly does the job. Now the type can be passed as I whished to and the factory creates the right sub-type. – babu67 Mar 09 '13 at 15:12