Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
October 19, 2014 Base class with member parameterized on type of extending class | ||||
---|---|---|---|---|
| ||||
I'm trying to make a game, and would like to set up the following hierarchy: At any time, the game is in one Scene. Each scene has a state machine that manages States of type T, where T is the type of the scene (e.g. Overworld, Menu). abstract class State!T { void update(T scene, float time, InputManager input); ... } class StateMachine!T { //manages states of type State!T } abstract class Scene { alias T = // type of class extending Scene // methods pushState, popState, currentState access _stateMachine private StateMachine!T _stateMachine; } class MainMenu : Scene { // I want _stateMachine of type StateMachine!MainMenu } class Overworld : Scene { // I want _stateMachine of type StateMachine!Overworld } class MoveToLocation : State!Overworld { override void update(Overworld world, float time, InputManager input) { // access properties of Overworld here } } Within the Scene class, I've tried alias T = typeof(this), but that appears to be resolved within Scene. This means that any Scene, such as Overworld, have a state machine of type StateMachine!Scene rather than StateMachine!Overworld. Since States are particular to a certain scene and are designed to manipulate properties specific to that type of scene, this would involve a lot of casting if States are not parameterized. It feels like I need something like a class version of the (this T) syntax used in templates. This all smells a bit off though, so I wouldn't be surprised if the answer is that I'm approaching this all wrong, but right now I'm not seeing it. |
October 20, 2014 Re: Base class with member parameterized on type of extending class | ||||
---|---|---|---|---|
| ||||
Posted in reply to rcor | On 2014-10-19 13:19, rcor wrote: > I'm trying to make a game, and would like to set up the following > hierarchy: > At any time, the game is in one Scene. Each scene has a state machine > that manages States of type T, where T is the type of the scene (e.g. > Overworld, Menu). > > abstract class State!T { > void update(T scene, float time, InputManager input); > ... > } > > class StateMachine!T { //manages states of type State!T } > > abstract class Scene { > alias T = // type of class extending Scene > // methods pushState, popState, currentState access _stateMachine > private StateMachine!T _stateMachine; > } > > class MainMenu : Scene { > // I want _stateMachine of type StateMachine!MainMenu > } > > class Overworld : Scene { > // I want _stateMachine of type StateMachine!Overworld > } > > class MoveToLocation : State!Overworld { > override void update(Overworld world, float time, InputManager input) { > // access properties of Overworld here > } > } > > Within the Scene class, I've tried alias T = typeof(this), but that > appears to be resolved within Scene. This means that any Scene, such as > Overworld, have a state machine of type StateMachine!Scene rather than > StateMachine!Overworld. Since States are particular to a certain scene > and are designed to manipulate properties specific to that type of > scene, this would involve a lot of casting if States are not > parameterized. It feels like I need something like a class version of > the (this T) syntax used in templates. > > This all smells a bit off though, so I wouldn't be surprised if the > answer is that I'm approaching this all wrong, but right now I'm not > seeing it. You can always make Scene a template class: abstract class Scene (T) { private StateMachine!T _stateMachine; } class MainMenu : Scene!(MainMenu) {} But I'm guessing you like to avoid that if possible. -- /Jacob Carlborg |
October 20, 2014 Re: Base class with member parameterized on type of extending class | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On Monday, 20 October 2014 at 06:17:42 UTC, Jacob Carlborg wrote:
>
> You can always make Scene a template class:
>
> abstract class Scene (T)
> {
> private StateMachine!T _stateMachine;
> }
>
> class MainMenu : Scene!(MainMenu) {}
>
> But I'm guessing you like to avoid that if possible.
I would, as I need to keep track of the current scene in a variable somewhere:
Scene _currentScene; // problematic if Scene is a template
I could just declare the StateMachine separately in every Scene, but that seems like a lot of duplicate code (I then repeat the same code for updating the state machine, ect.)
|
October 20, 2014 Re: Base class with member parameterized on type of extending class | ||||
---|---|---|---|---|
| ||||
Posted in reply to rcor | On 2014-10-20 12:27, rcor wrote: > I would, as I need to keep track of the current scene in a variable > somewhere: > > Scene _currentScene; // problematic if Scene is a template If the state machine doesn't need to be exposed you can create base class for Scene which is not templated: abstract class Scene {} // As it is now minus the state machine abstract class ConcreteScene (T) : Scene { private StateMachine!T _stateMachine; // other code that need access to _stateMachine } class MainMenu : ConcreteScene!(MainMenu) {} Scene _currentScene = new MainMenu; "ConcreteScene" might not be the best name of an abstract class. > I could just declare the StateMachine separately in every Scene, but > that seems like a lot of duplicate code (I then repeat the same code for > updating the state machine, ect.) Or you could use a template mixin: template StateMachineMixin (T) { private StateMachine!T _stateMachine; // other code that need access to _stateMachine } class MainMenu : Scene { mixin StateMachineMixin!(typeof(this)); } -- /Jacob Carlborg |
October 20, 2014 Re: Base class with member parameterized on type of extending class | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | > If the state machine doesn't need to be exposed you can create base class for Scene which is not templated: > > abstract class Scene {} // As it is now minus the state machine > > abstract class ConcreteScene (T) : Scene > { > private StateMachine!T _stateMachine; > > // other code that need access to _stateMachine > } > > class MainMenu : ConcreteScene!(MainMenu) {} > > Scene _currentScene = new MainMenu; > > "ConcreteScene" might not be the best name of an abstract class. > Just came up with something similar before I saw this post: interface IScene { // enter, exit, update, draw } class Scene!T : IScene { private StateMachine!T _stateMachine; void update(float time) { _stateMachine.update(cast(T) this, time); } } The cast is unfortunate but since it only happens once per update cycle I'm not that worried about it. >> I could just declare the StateMachine separately in every Scene, but >> that seems like a lot of duplicate code (I then repeat the same code for >> updating the state machine, ect.) > > Or you could use a template mixin: > > template StateMachineMixin (T) > { > private StateMachine!T _stateMachine; > > // other code that need access to _stateMachine > } > > class MainMenu : Scene > { > mixin StateMachineMixin!(typeof(this)); > } Interesting idea, I might give this a try but the first suggestion seems fine for now. Thanks! |
Copyright © 1999-2021 by the D Language Foundation