Thread overview
Auto-add static field when inherit // mixins, templates?
Aug 21, 2014
MarisaLovesUsAll
Aug 21, 2014
MarisaLovesUsAll
Aug 21, 2014
anonymous
Aug 21, 2014
MarisaLovesUsAll
Aug 21, 2014
anonymous
Aug 21, 2014
MarisaLovesUsAll
Aug 21, 2014
Ary Borenszweig
Aug 21, 2014
anonymous
August 21, 2014
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
August 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
August 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) {}
}
August 21, 2014
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
August 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

Bar.new.method_in_bar #=> "Hello Bar!"
~~~

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)
August 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.
August 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
>
> Bar.new.method_in_bar #=> "Hello Bar!"
> ~~~

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();
}
August 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
August 22, 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.