www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Auto-add static field when inherit // mixins, templates?

reply "MarisaLovesUsAll" <marisalovesusall gmail.com> writes:
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
next sibling parent reply "MarisaLovesUsAll" <marisalovesusall gmail.com> writes:
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
parent reply "anonymous" <anonymous example.com> writes:
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
parent reply "MarisaLovesUsAll" <marisalovesusall gmail.com> writes:
On Thursday, 21 August 2014 at 13:19:06 UTC, anonymous wrote:
 1) How to make mixin inject automatic?
You could use this pattern: interface Component {} class ComponentImpl(T) {} class Sprite : ComponentImpl!Sprite {}
From my view, it's an architectural crutch. %)
 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
parent reply "anonymous" <anonymous example.com> writes:
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
parent "MarisaLovesUsAll" <marisalovesusall gmail.com> writes:
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
prev sibling next sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
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
parent "anonymous" <anonymous example.com> writes:
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
prev sibling parent "Chris Nicholson-Sauls" <ibisbasenji gmail.com> writes:
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