digitalmars.D.learn - Auto-add static field when inherit // mixins, templates?
- MarisaLovesUsAll (40/40) Aug 21 2014 tl;dr - how to get child classname from inherited parent function
- MarisaLovesUsAll (15/55) Aug 21 2014 I found a rough solution. It's not ideal and I still want to make
- anonymous (15/27) Aug 21 2014 You could use this pattern:
- MarisaLovesUsAll (24/34) Aug 21 2014 Thanks, it works.
- anonymous (5/20) Aug 21 2014 I don't think this is possible.
- MarisaLovesUsAll (42/44) Aug 21 2014 Sure.
- Ary Borenszweig (24/63) Aug 21 2014 I'll tell you how it's done in Crystal in case someone wants to come up
- anonymous (21/35) Aug 21 2014 I think such a feature would clash with a D principle: A base
- Chris Nicholson-Sauls (20/20) Aug 21 2014 class A
tl;dr - how to get child classname from inherited parent function
at compile time?
class A { string getName(); };
class B { };
B foo = new B;
assert(foo.getName() == "B");
...
Hi! I'm stuck at one issue, and I don't know how to solve it. I
think this is about mixins/templates, isn't it?
When inherit from base class Component, I need to auto-create
child own static fields with child type.
It should look like this, after compilation:
class Component
{
//it doesn't matter to have any fields here
//but it's important to be able to create an instance of
Component
//and when inherit, all childs will get their own "static T
list;" where T is a type of child.
};
class Sprite:Component
{
static Sprite list; //auto-added
static void fun() { } //auto-added, operates with Sprite
}
class Camera:Component
{
static Camera list; //auto-added
static void fun() { } //auto-added, operates with Camera
instead of Sprite
}
...
//so this must be correct:
Component foo;
Sprite bar;
void foobar(Component one) { }
foobar(Sprite);
...
Sorry for bad English.
Best regards, Alex
Aug 21 2014
I found a rough solution. It's not ideal and I still want to make
autoinject, but it works.
mixin template Manager(T) {};
class Component {};
class Sprite:Component
{
mixin Manager!Sprite;
};
1) How to make mixin inject automatic?
2) If it's impossible, how to use "mixin Manager;" without
"!Sprite" ?
"mixin template Manager(this T) {};" isn't working.
Regards, Alex
On Thursday, 21 August 2014 at 09:38:13 UTC, MarisaLovesUsAll
wrote:
tl;dr - how to get child classname from inherited parent
function at compile time?
class A { string getName(); };
class B { };
B foo = new B;
assert(foo.getName() == "B");
...
Hi! I'm stuck at one issue, and I don't know how to solve it. I
think this is about mixins/templates, isn't it?
When inherit from base class Component, I need to auto-create
child own static fields with child type.
It should look like this, after compilation:
class Component
{
//it doesn't matter to have any fields here
//but it's important to be able to create an instance of
Component
//and when inherit, all childs will get their own "static T
list;" where T is a type of child.
};
class Sprite:Component
{
static Sprite list; //auto-added
static void fun() { } //auto-added, operates with Sprite
}
class Camera:Component
{
static Camera list; //auto-added
static void fun() { } //auto-added, operates with Camera
instead of Sprite
}
...
//so this must be correct:
Component foo;
Sprite bar;
void foobar(Component one) { }
foobar(Sprite);
...
Sorry for bad English.
Best regards, Alex
Aug 21 2014
On Thursday, 21 August 2014 at 12:58:13 UTC, MarisaLovesUsAll wrote:I found a rough solution. It's not ideal and I still want to make autoinject, but it works. mixin template Manager(T) {}; class Component {}; class Sprite:Component { mixin Manager!Sprite; }; 1) How to make mixin inject automatic?You could use this pattern: interface Component {} class ComponentImpl(T) {} class Sprite : ComponentImpl!Sprite {} It's not 100% automatic, but the duplication of "Sprite" is in the same line. And it's not as easy to forget as a mixin, especially when Component does declare methods that ComponentImpl implements.2) If it's impossible, how to use "mixin Manager;" without "!Sprite" ? "mixin template Manager(this T) {};" isn't working.You can use `typeof(this)` in Manager: mixin template Manager() { void someMethod(typeof(this) otherInstance) {} }
Aug 21 2014
On Thursday, 21 August 2014 at 13:19:06 UTC, anonymous wrote:From my view, it's an architectural crutch. %)1) How to make mixin inject automatic?You could use this pattern: interface Component {} class ComponentImpl(T) {} class Sprite : ComponentImpl!Sprite {}You can use `typeof(this)` in Manager: mixin template Manager() { void someMethod(typeof(this) otherInstance) {} }Thanks, it works. ...I also have more questions %) When I make mixin injection in one class, I want auto-injection in another class. How can I do this? class Component:GameObject { //second injection must be here and must be automatic }; class Sprite:Component { mixin Manager; //first injection must activate second injection by misterious way }; mixin template Manager() {} mixin template ComponentCaster(string type) {} //where 'type' is a type obtained from Manager //by typeof(this).stringof. As example, "Sprite". ...compile-time code generation is pain %) I think, it will be 50 times easier if we have built-in compiler script language. Or just a library that will be able to execute code in compile time. Sorry for Engrish. Regards, Alex
Aug 21 2014
On Thursday, 21 August 2014 at 19:58:18 UTC, MarisaLovesUsAll wrote:When I make mixin injection in one class, I want auto-injection in another class. How can I do this? class Component:GameObject { //second injection must be here and must be automatic }; class Sprite:Component { mixin Manager; //first injection must activate second injection by misterious way };I don't think this is possible.mixin template Manager() {} mixin template ComponentCaster(string type) {} //where 'type' is a type obtained from Manager //by typeof(this).stringof. As example, "Sprite".Maybe you can explain what you're trying to achieve with all this. There may be a different/better way to do it.
Aug 21 2014
On Thursday, 21 August 2014 at 20:16:33 UTC, anonymous wrote:Maybe you can explain what you're trying to achieve with all this. There may be a different/better way to do it.Sure. Class tree: GameObject->Component->Sprite. GameObject structure: Component[]; Component addComponent(Component component); First feature is Components Manager. It's an array and register()/remove() functions, just like in GameObject, but it's static and unique to all inherited classes. static T[] list; static void register(T obj); static void remove(T obj); So, if I do this class Sprite:Component {}; 'T' becomes 'Sprite', and Manager functionality adds to class. It also will be able to create instance of class Component because of Components list in GameObject. And Component type must be one because it's easier to use one name for inheritance and for storing Components. I did this by mixins, but it's not automatic. And second feature. When I create Sprite and add it in GameObject, there will be no 'cast(Sprite)' constructions; type of return value must be argument's type. Code: Component addComponent(Component component); Sprite shell = cast(Sprite) this.addComponent(new Sprite("shell_1.png")); //I want remove 'cast(Sprite)' from here I found a solution for one class: class Component { Sprite toSprite() property { return cast(Sprite) this; } alias toSprite this; } And it works. Now I want to add this solution in class Component, working with all inherited classes. As I realize, this is rough and impossible, and I need to do some template magic in GameObject code. Sorry for Engrish. Regards, Alex
Aug 21 2014
On 8/21/14, 6:38 AM, MarisaLovesUsAll wrote:
tl;dr - how to get child classname from inherited parent function at
compile time?
class A { string getName(); };
class B { };
B foo = new B;
assert(foo.getName() == "B");
...
Hi! I'm stuck at one issue, and I don't know how to solve it. I think
this is about mixins/templates, isn't it?
When inherit from base class Component, I need to auto-create child own
static fields with child type.
It should look like this, after compilation:
class Component
{
//it doesn't matter to have any fields here
//but it's important to be able to create an instance of Component
//and when inherit, all childs will get their own "static T list;"
where T is a type of child.
};
class Sprite:Component
{
static Sprite list; //auto-added
static void fun() { } //auto-added, operates with Sprite
}
class Camera:Component
{
static Camera list; //auto-added
static void fun() { } //auto-added, operates with Camera instead of
Sprite
}
...
//so this must be correct:
Component foo;
Sprite bar;
void foobar(Component one) { }
foobar(Sprite);
...
Sorry for bad English.
Best regards, Alex
I'll tell you how it's done in Crystal in case someone wants to come up
with a proposal to make it work in D.
~~~
class Foo
macro inherited
def method_in_{{ class_name.downcase.id}}
puts "Hello {{ class_name.id}}!"
end
end
end
class Bar < Foo
end
~~~
When you inherit a class, the macro "inherited" is automatically
executed by the compiler in the context of the inheriting class. There
you can use special variables like " class_name" and interpolate them
with {{ ... }}.
I guess a similar thing to do in D would be to define a function to be
executed at compile time and automatically mix it, and the context of
execution would be the inherited class.
(sorry if this is of no interest to all of you, let me know if I should
stop trying to bring ideas to D from other languages)
Aug 21 2014
On Thursday, 21 August 2014 at 20:05:13 UTC, Ary Borenszweig
wrote:
I'll tell you how it's done in Crystal in case someone wants to
come up with a proposal to make it work in D.
~~~
class Foo
macro inherited
def method_in_{{ class_name.downcase.id}}
puts "Hello {{ class_name.id}}!"
end
end
end
class Bar < Foo
end
~~~
I think such a feature would clash with a D principle: A base
class (Foo) cannot know about (or depend on) all its subclasses
(Bar), because it may be compiled separately from them.
Now, if it were only about printing the most derived class name
(I know, it isn't), you could that in D with typeid:
import std.stdio;
class Foo
{
void whoami()
{
writeln(typeid(this));
}
}
class Bar : Foo {}
void main()
{
Foo f = new Bar;
f.whoami();
}
Aug 21 2014
class A
{
string getName(this Klass)()
{
return Klass.stringof;
}
}
class B : A
{}
void main()
{
import std.stdio;
auto a = new A;
auto b = new B;
writeln(a.getName());
writeln(b.getName());
}
This is about as close as you're going to get without some
hackery.
Aug 21 2014









"MarisaLovesUsAll" <marisalovesusall gmail.com> 