digitalmars.D.learn - change object class
- Vitaliy Fadeev (53/53) Sep 17 2023 Hi!
- Vitaliy Fadeev (3/4) Sep 17 2023 Playground: https://run.dlang.io/is/hjcLCk
- evilrat (21/24) Sep 17 2023 If that works for you with that constraint of having exact memory
- Johan (6/13) Sep 17 2023 No, this is Undefined Behavior and will likely cause you trouble
- Imperatorn (3/9) Sep 21 2023 Interesting, but why would you want to do it that way? 😳
- Vitaliy Fadeev (14/29) Sep 21 2023 Q & A.
- Vitaliy Fadeev (35/36) Sep 21 2023 ```
- Vitaliy Fadeev (21/24) Sep 21 2023 the most correct
- Imperatorn (4/40) Sep 22 2023 What I mean is, why not use other language constructs like mixins
- Vitaliy Fadeev (2/48) Sep 22 2023 Can you give an example?
- Imperatorn (4/12) Sep 22 2023 You're basically just describing polymorphism. I can post an
- Vitaliy Fadeev (3/8) Sep 22 2023 Thank you. Of course! It's interesting to look at the solutions
- =?UTF-8?Q?Christian_K=c3=b6stlin?= (9/72) Sep 22 2023 You could model it oop style like this:
- Vitaliy Fadeev (18/23) Sep 22 2023 Thank, Christian !
- =?UTF-8?Q?Christian_K=c3=b6stlin?= (23/49) Sep 22 2023 VTable is your structure .. it does exactly what you want it to do.
- Vitaliy Fadeev (7/20) Sep 22 2023 ```Behavior``` is beautiful code!
- =?UTF-8?Q?Christian_K=c3=b6stlin?= (6/27) Sep 22 2023 Here a solution with less `new`s: https://run.dlang.io/is/iV1qVq.
Hi! I want to change a method ```Draw``` on a custom object when the ```MouseIn``` event occurs. This is known as "Change State" of the object: ```Init``` -> ```Hovered```. I want to change the state of an object by changing its class, like this: ```d this.__vptr = typeid(CLS).vtbl.ptr; ``` I have read the ABI and am confident in replacing ```__vptr``` as long as the classes contain the same fields and the same interfaces. Example: ```d // O // to!state // State_Init : O // Draw // State_Hovered : O // Draw // // o.to!State_Hovered // o.to!State_Init class O { void to(CLS)() { // if (same fields && same interfaces && same instance size) this.__vptr = cast(immutable(void*)*)typeid(CLS).vtbl.ptr; } } State_Init : O void Draw() { /* ... */ } State_Hovered : O void Draw() { /* ... */ } ``` when MouseIn: ```d ... o.to!State_Hovered(); ... ``` when MouseOut: ```d ... o.to!State_Init(); ... ``` It works! But I want to ask how to make this 100% the best of the best? What should I consider before changing ```__vptr``` ?
Sep 17 2023
On Sunday, 17 September 2023 at 15:05:59 UTC, Vitaliy Fadeev wrote:...Playground: https://run.dlang.io/is/hjcLCk
Sep 17 2023
On Sunday, 17 September 2023 at 15:05:59 UTC, Vitaliy Fadeev wrote:It works! But I want to ask how to make this 100% the best of the best? What should I consider before changing ```__vptr``` ?If that works for you with that constraint of having exact memory layout then it should be ok. This however is very uncommon pattern and your library users might reject it so keep that in mind if you are going to make public library. Other than that I would suggest at least to make that cast method to return a shallow copy because messing with "this" ptr can be dangerous (make sure to try it with const objects and optimized release builds before using this everywhere). An even better (at least safer, in theory) option would be to make "View" or handle struct that wraps an object(pointer) and tracks such transformations. Of course to think of it now there is yet another opportunity - why not to look for something like ECS then? Because you seem to already treat your objects purely as data containers, that way you can safely detach data from logic and reduce the scope of your components to keep them focused on one task. That is up to you of course.
Sep 17 2023
On Sunday, 17 September 2023 at 17:10:16 UTC, evilrat wrote:On Sunday, 17 September 2023 at 15:05:59 UTC, Vitaliy Fadeev wrote:No, this is Undefined Behavior and will likely cause you trouble in the future (as in: some very hard to debug bugs may appear). Better to store the state in the object and select the behavior using a switch on the state. -JohanIt works! But I want to ask how to make this 100% the best of the best? What should I consider before changing ```__vptr``` ?If that works for you with that constraint of having exact memory layout then it should be ok.
Sep 17 2023
On Sunday, 17 September 2023 at 15:05:59 UTC, Vitaliy Fadeev wrote:Hi! I want to change a method ```Draw``` on a custom object when the ```MouseIn``` event occurs. This is known as "Change State" of the object: ```Init``` -> ```Hovered```. [...]Interesting, but why would you want to do it that way? 😳
Sep 21 2023
On Thursday, 21 September 2023 at 18:19:47 UTC, Imperatorn wrote:On Sunday, 17 September 2023 at 15:05:59 UTC, Vitaliy Fadeev wrote:Q & A. You can check the logic.Hi! I want to change a method ```Draw``` on a custom object when the ```MouseIn``` event occurs. This is known as "Change State" of the object: ```Init``` -> ```Hovered```. [...]Interesting, but why would you want to do it that way? 😳How to increase the battery life of a smartphone?Reducing operations.How to change the state of a button widget, for example, on mouseover?By changing the pointer to the Draw method.In addition to Draw, the widget has a Sense method. How to replace all pointers to methods at once?Replace the pointer with a class. (It's like a change of state! Exactly Turing's State Machine.) The object fields are the same. Behavior changes. The contents of the fields remain in memory. Only the pointer to the method table changes. Of course, this requires care and forethought. Perhaps the risks of changing class can be reduced by performing additional checks. Changing class is a convenient tool. I want to use it.
Sep 21 2023
On Friday, 22 September 2023 at 02:51:10 UTC, Vitaliy Fadeev wrote:...``` Chip id name Sense() Draw() ``` instance ``` chip = new Chip(); ``` compiled to ``` chip __vtbl -------------> Chip __monitor Sense() id Draw() name ``` I want ``` chip __vtbl --+ id | name | |-> Chip_Hovered | Sense() | Draw() | +-> Chip_Hovered Sense() Draw() ```
Sep 21 2023
On Friday, 22 September 2023 at 03:33:08 UTC, Vitaliy Fadeev wrote:On Friday, 22 September 2023 at 02:51:10 UTC, Vitaliy Fadeev wrote:the most correct ``` chip __vtbl ---+ // one of __monitor | id | name | |-> Chip // init | Sense() | Draw() | |-> Chip_Hovered // on mouseover | Sense() | Draw() | +-> Chip_Selected // on mouseclick Sense() Draw() ```...
Sep 21 2023
On Friday, 22 September 2023 at 03:33:08 UTC, Vitaliy Fadeev wrote:On Friday, 22 September 2023 at 02:51:10 UTC, Vitaliy Fadeev wrote:What I mean is, why not use other language constructs like mixins or inheritance with some mapping for example?...``` Chip id name Sense() Draw() ``` instance ``` chip = new Chip(); ``` compiled to ``` chip __vtbl -------------> Chip __monitor Sense() id Draw() name ``` I want ``` chip __vtbl --+ id | name | |-> Chip_Hovered | Sense() | Draw() | +-> Chip_Hovered Sense() Draw() ```
Sep 22 2023
On Friday, 22 September 2023 at 12:53:28 UTC, Imperatorn wrote:On Friday, 22 September 2023 at 03:33:08 UTC, Vitaliy Fadeev wrote:Can you give an example?On Friday, 22 September 2023 at 02:51:10 UTC, Vitaliy Fadeev wrote:What I mean is, why not use other language constructs like mixins or inheritance with some mapping for example?...``` Chip id name Sense() Draw() ``` instance ``` chip = new Chip(); ``` compiled to ``` chip __vtbl -------------> Chip __monitor Sense() id Draw() name ``` I want ``` chip __vtbl --+ id | name | |-> Chip_Hovered | Sense() | Draw() | +-> Chip_Hovered Sense() Draw() ```
Sep 22 2023
On Friday, 22 September 2023 at 14:03:40 UTC, Vitaliy Fadeev wrote:On Friday, 22 September 2023 at 12:53:28 UTC, Imperatorn wrote:You're basically just describing polymorphism. I can post an example tomorrow, it's midnight here now.On Friday, 22 September 2023 at 03:33:08 UTC, Vitaliy Fadeev wrote:Can you give an example?[...]What I mean is, why not use other language constructs like mixins or inheritance with some mapping for example?
Sep 22 2023
On Friday, 22 September 2023 at 21:37:37 UTC, Imperatorn wrote:On Friday, 22 September 2023 at 14:03:40 UTC, Vitaliy Fadeev wrote:Thank you. Of course! It's interesting to look at the solutions to choose the best one.On Friday, 22 September 2023 at 12:53:28 UTC, Imperatorn wrote:You're basically just describing polymorphism. I can post an example tomorrow, it's midnight here now.
Sep 22 2023
On 17.09.23 17:05, Vitaliy Fadeev wrote:Hi! I want to change a method ```Draw``` on a custom object when the ```MouseIn``` event occurs. This is known as "Change State" of the object: ```Init``` -> ```Hovered```. I want to change the state of an object by changing its class, like this: ```d this.__vptr = typeid(CLS).vtbl.ptr; ``` I have read the ABI and am confident in replacing ```__vptr``` as long as the classes contain the same fields and the same interfaces. Example: ```d // O //  to!state // State_Init   : O //  Draw // State_Hovered : O //  Draw // // o.to!State_Hovered // o.to!State_Init class O {  void to(CLS)()  {    // if (same fields && same interfaces && same instance size)    this.__vptr =      cast(immutable(void*)*)typeid(CLS).vtbl.ptr;  } } State_Init : O  void Draw() { /* ... */ } State_Hovered : O  void Draw() { /* ... */ } ``` when MouseIn: ```d  ...  o.to!State_Hovered();  ... ``` when MouseOut: ```d  ...  o.to!State_Init();  ... ``` It works! But I want to ask how to make this 100% the best of the best? What should I consider before changing ```__vptr``` ?You could model it oop style like this: https://run.dlang.io/is/MJb5Fk This solution might not be to your taste, as it involves interfaces, and classes and objects and garbage (all the news) ... another option could be to model your own VTable in a struct like this: https://run.dlang.io/is/3LTjP5 Kind regards, Christian
Sep 22 2023
On Friday, 22 September 2023 at 19:50:17 UTC, Christian Köstlin wrote:another option could be to model your own VTable in a struct like this: https://run.dlang.io/is/3LTjP5 Kind regards, ChristianThank, Christian ! True nice tasty solution with ```VTable```! And further... the project is growing. ``` void Draw() { DrawBG(); DrawFG(); } ``` And we want use ```DrawBG()``` code from ```initial``` in other states, like ```Selected```. How to use some functions from ```initial``` via ```VTable``` ? I see solution in ```classes``` and methods with ```override``` keyword. ```VTable``` does the same thing as ```__vptr``` ?
Sep 22 2023
On 23.09.23 05:11, Vitaliy Fadeev wrote:On Friday, 22 September 2023 at 19:50:17 UTC, Christian Köstlin wrote:VTable is your structure .. it does exactly what you want it to do. __vptr is the internal implementation of virtual methods in the dlang object model. Line 20 and 21 in my example initialize the two `VTable`s Initial and Hovered. You can change VTable to contain two function pointers and initialize those as you like for the instances of the VTable structs. e.g. ```d struct DrawVTable { void function(Chip, Renderer) background; void function(Chip, Renderer) foreground; } // define functions to draw the different fore and backgrounds ... ... VTable initial = VTable(&drawInitialBackground, &drawInitialForeground); VTable hovered = VTable(&drawHoveredBackground, &drawHoveredForeground); VTable selected = VTable(&drawInitialBackground, &drawHoveredForegtround); ``` Kind regards, Christiananother option could be to model your own VTable in a struct like this: https://run.dlang.io/is/3LTjP5 Kind regards, ChristianThank, Christian ! True nice tasty solution with ```VTable```! And further... the project is growing. ``` void Draw() {  DrawBG();  DrawFG(); } ``` And we want use ```DrawBG()``` code from ```initial``` in other states, like ```Selected```. How to use some functions from ```initial``` via ```VTable``` ? I see solution in ```classes``` and methods with ```override``` keyword. ```VTable``` does the same thing as ```__vptr``` ?
Sep 22 2023
On Friday, 22 September 2023 at 19:50:17 UTC, Christian Köstlin wrote:On 17.09.23 17:05, Vitaliy Fadeev wrote:```Behavior``` is beautiful code! But it contains a second ```new``` when ```Chip``` is created. One ```new``` is possible? Christian, really nice code! Does ```__vptr``` do the same thing ?Hi!You could model it oop style like this: https://run.dlang.io/is/MJb5Fk This solution might not be to your taste, as it involves interfaces, and classes and objects and garbage (all the news) ... another option could be to model your own VTable in a struct like this: https://run.dlang.io/is/3LTjP5 Kind regards, Christian
Sep 22 2023
On 23.09.23 05:25, Vitaliy Fadeev wrote:On Friday, 22 September 2023 at 19:50:17 UTC, Christian Köstlin wrote:Here a solution with less `new`s: https://run.dlang.io/is/iV1qVq. It really depends on the program that you are doing if creating those news is a problem. Kind regards, ChristianOn 17.09.23 17:05, Vitaliy Fadeev wrote:```Behavior``` is beautiful code! But it contains a second ```new``` when ```Chip``` is created. One ```new``` is possible? Christian, really nice code!Hi!You could model it oop style like this: https://run.dlang.io/is/MJb5Fk This solution might not be to your taste, as it involves interfaces, and classes and objects and garbage (all the news) ... another option could be to model your own VTable in a struct like this: https://run.dlang.io/is/3LTjP5 Kind regards, Christian
Sep 22 2023