Search code examples
interfaced

Unable to pass interface as pointer in D language


I have no idea what is going on here. Please explain. Code...

import std.stdio;

void main(string[] args)
{
    ClassObject ss1 = new ClassObject("First Class");
    writeln(ss1.produce());
    ClassObject ss2 = new ClassObject("Some Class");
    ClassObject* ss3 = &ss2;
    voidclass(ss3);
    ClassObject ss4 = new ClassObject("Final Class");
    passinterface(ss4);
    ClassObject* ss5 = &ss4;
    writeln(ss5.produce());
    voidinterface(ss5);
}

public void voidclass(void* arg)
{
    ClassObject* ss = cast(ClassObject*) arg;
    writeln(ss.produce());
    writeln(ss.produce);
    ClassObject ssnp = *ss;
    writeln(ssnp.produce());
    writeln(ssnp.produce);
}

public void voidinterface(void* arg)
{
    IObject* bob = cast(IObject*) arg;
    writeln(bob.produce());
}

public void passinterface(IObject arg)
{
    writeln(arg.produce());
}

interface IObject
{
    string produce();
}

class ClassObject : IObject
{
    protected string _value;

    this(string value)
    {
        this._value = value;
    }

    public string produce()
    {
        return this._value;
    }
}

Output...

First Class
Some Class
Some Class
Some Class
Some Class
Final Class
Final Class
main.ClassObject

What is going on with that final output? I pass a class instance to a function that expects a pointer. Then when I cast it as an interface it doesn't respect the methods of the interface. But some how is able to tell this an instance of the class I passed?

And sadly I am binding to a C library so I have to use void* as the argument type. So please don't suggest not using it.

Edit: Compiler information...

$ dmd -v
DMD64 D Compiler v2.062
Copyright (c) 1999-2012 by Digital Mars written by Walter Bright
Documentation: http://dlang.org/

Solution

  • Pointers in D are not polymorphic. Only class references are. As soon as you're operating through a pointer, you lose polymorphism.

    Also, &ss2 does not result in a pointer to a class. It results in pointer to a reference to class. You can't have pointers to class objects in D, only references to class objects. The type system does not really differentiate between a class reference and the object that it refers to, which is why std.typecons.Rebindable is required if you want to have a non-const reference to a const class object.

    You can however cast a class reference to and from void* if you really need to use void* for some reason - though you really should avoid it in general. Using void* means that you lose type information, and the compiler can't protect you. While it's occasionally useful (particularly when interacting with C), there's not much reason to use void* in D.