Alternative to Interfaces

H. S. Teoh hsteoh at quickfur.ath.cx
Fri Jan 18 01:00:33 UTC 2019


On Fri, Jan 18, 2019 at 12:08:00AM +0000, 1001Days via Digitalmars-d-learn wrote:
> Hello,
> 
> Preface: I do apologize if this is too simplistic of a matter, and if
> I need to RTFM. I'm quite slow.
> 
> I want to use Structs instead of Classes, but I don't want to lose the
> abilities of Interfaces. So instead I used a combination of templates,
> constraints, the hasMember trait, and delegates to achieve a simple
> alternative.

Maybe you could help us answer your question better by explaining a bit
more what you're trying to achieve.  Generally, if you want to use an
interface, that usually means you want (1) runtime polymorphism, i.e.,
the ability to swap one concrete implementation for another at runtime,
and (2) pass around possibly different concrete objects to code that
expects objects of a single type (the interface type).

So the first question is, do you need runtime polymorphism? Do you need
to pass objects of different types to functions that only take a single
type?  Do you need the ability to change *at runtime* the type of object
passed to a function?

If so, you probably should stick with interfaces and classes.  While it
*is* possible to achieve equivalent functionality with structs and
templates, you'll basically end up reinventing classes, possibly poorly,
and spending coding / debugging time doing so when you could have just
used the built-in construct.

If the reason you're using structs is just to avoid the GC, then you
should look up emplace() in the docs.  It *is* possible to use classes
without using the GC.  Just in case you didn't know.

OTOH, if you don't need runtime polymorphism, then using classes and
templates would be the "more idiomatic" way to do it. (Though you should
also keep in mind the possible drawbacks of template bloat -- which may
cause more instruction cache misses by making your code larger than it
could have been.)


> It works, but I have two questions regarding its efficacy: is it
> viable in the long run, and is it now possible to use delegates
> without the GC? The latter is of particular importance as I'm using
> Structs for compatibility.
[...]

Whether or not it's viable really depends on whether you need runtime
polymorphism, and what you're trying to accomplish.

My personal tendency is to start with structs and compile-time
introspection as an initial stab, but depending on what might be needed,
I may use some classes / interfaces.  The two can be combined to some
extent -- e.g., a template function can take both structs with
compile-time introspection and also classes that allow runtime
polymorphism.  A template function instantiated with a class type will
be able to accept different concrete objects at runtime (as long as they
are subclasses of that type).  However, it will only be able to "see"
the static info of the class it was instantiated with, not any
additional features of derived classes that it may receive at runtime,
since there will be no runtime introspection.

Though AFAIK, delegates probably still need heap allocation and depend
on the GC, esp. if you have closures over local variables.  There may be
some cases where the compiler will elide this, e.g., if you have a
function literal passed via an alias that does not escape the caller's
scope.  OTOH, you might be able to get around needing the GC if you put
your delegates in an emplace()'d class as methods, and take their
address (which produces a delegate).  Just make sure your class doesn't
go out of scope while the resulting delegates are still around. Keep in
mind that in this case, you will not be able to have closure over local
variables (delegates can only have 1 context pointer, and in this case
it's already used up by the `this` reference) and will have to store any
such contextual information inside the class itself.


T

-- 
It always amuses me that Windows has a Safe Mode during bootup. Does that mean that Windows is normally unsafe?


More information about the Digitalmars-d-learn mailing list