Add a variable to a class instance at runtime: Difference between revisions

Content deleted Content added
Bartj (talk | contribs)
Rewritten D entries
Line 191: Line 191:


=={{header|D}}==
=={{header|D}}==
<lang d>struct Dynamic(T) {
D is a statically compiled language, so there are some limits.
private T[string] vars;
This adds a new 'attribute' to a struct/class instance, of type T:
<lang d>import std.stdio: writeln;
import std.traits: isImplicitlyConvertible;


@property T opDispatch(string key)() pure nothrow {
struct S(T) {
T[string] data;
return vars[key];
}


template opDispatch(string name) {
@property void opDispatch(string key, U)(U value)/*pure*/ nothrow {
vars[key] = value;
T opDispatch(Types...)(Types args)
}
if (!args.length || (args.length == 1 && isImplicitlyConvertible!(Types[0],T))) {
static if (args.length) {
data[name] = args[0];
return args[0];
} else
return data[name];
}
}
}
}


void main() {
void main() {
import std.variant, std.stdio;
S!long s;

s.foo = 1;
// If the type of the attributes is known at compile-time:
writeln(s.foo());
auto d1 = Dynamic!double();
d1.first = 10.5;
d1.second = 20.2;
writeln(d1.first, " ", d1.second);


// If the type of the attributes is mixed:
auto d2 = Dynamic!Variant();
d2.a = "Hello";
d2.b = 11;
d2.c = ['x':2, 'y':4];
writeln(d2.a, " ", d2.b, " ", d2.c);
immutable int x = d2.b.get!int;
}</lang>
}</lang>
{{out}}
If the attribute name is not known at compile-time, you have to use a more normal syntax:
<pre>10.5 20.2
<lang d>import std.stdio: writeln;
Hello 11 ['x':2, 'y':4]</pre>
If you want Dynamic to be a class the code is similar. If the attribute names aren't known at compile-time, you have to use a more normal syntax:
<lang d>import std.stdio, std.variant, std.conv;


struct S(T) {
struct Dyn {
T[string] data;
Variant[string] data;
alias data this;
alias data this;
}
}


void main() {
void main(string[] args) {
S!long s;
Dyn d;
const attribute_name = text("attribute_", args.length);
string name = "bar";
s[name] = 2;
d[attribute_name] = "something";
writeln(s[name]);
writeln(d[attribute_name]);
}</lang>
}</lang>
{{out}}
If the type is variable it can be used an associative array of variants, but things become more complex. Adding a name to all instances of a class can be possible.
<pre>something</pre>


=={{header|Elena}}==
=={{header|Elena}}==