Sorry for the slow response
@GMWolf but it was a kind of holiday here where I am so I've been relaxing a bit.
Saying that instances execute code is a bit of a shortcut, and handy way to think about code.
I'm reality, of course, your cpu is executing the code.
What GM likely does, is keep a global 'running_instance' variable that denotes what the current instance is (accessible through the 'id' variable in GML).
Then when you read/write variables, or use certain functions it checks what the running_instance variable is, and applies the change to that instance.
Great info and ya I was speaking abstractly in my question.
It might keep around lists of instances for each type so that it doesn't have to iterate and check through each instance.
A 'with' block iterates through the instances that match the request, sets the running_instance variable for each, and runs the code.
Then it sets the variable back to what it was before the with block. (It might do that with a stack)
Yeah, GM being dynamic and all, I don't think you would end up with the diamond problem.
Though it would probably be best if they kept the single INHERITANCE (to inherit events), but introduced tags maybe.
So you could tag an object as "pushable", and then iterate through all "pushables".
Hmm, this is giving me an idea actually...
Shoot! Maybe we can come up with an alternative solution!
I'd love to come up with something with you (your tutorials have already been a great help to me in learning my way around GMS). Even just your comments in this post makes me think it would not be difficult at all to come up with something that functions exactly how I want it. In fact, the only thing I disagree with you about is including events in some form of multi inheritance. That seems exceptionally powerful to me with the caveat that you need to be careful you don't code yourself into the diamond problem. Since parenting in GM is basically just copy/pasting code into children's events, I just don't understand why inheritance HAS to be single inheritance in GM. Here's the beginning of a pretty simple (and lightweight?) strategy to introducing multi-inheritance in GM:
1. Have a singleton object called something like 'obj_components'
2. Have a bunch of lists in obj_components that instances in your game can add themselves to (e.g. list_pushables, list_characters, list_pickups but really the things you can't get to fit the single-inheritance parent/child hierarchy since you should just use that if you can)
3. Next have a parent object called something like 'par_multi_inheritor'
4. In each of par_multi_inheritor's step events just have a check to see if the child instance is in obj_components.list_pushables. If so, then run some code that you want all pushables to run for that event. Do the same for each other event as needed.
If all the things in your game that you want to have multiple inheritance can be a child of par_multi_inheritor, then that would cover the copy/paste part of the parent/child hierarchy without the restriction of single-inheritance. You could even have a list_non_inheritor that you add instances to that don't need any of the components, and just have a check at the beginning if the instance running the code for that event is in list_non_inheritor. If it is, then continue on, else do all the checks to see which components the instance has (i.e. which lists it is in). Some kind of optimization like this may be nice to skip unnecessary checks.
Your with-statements would have to be a bit different for any pushable (i.e. anything in list_pushables). So if you wanted to run some code on all your pushables, you would just loop through the instances in list_pushable and run the with-statement on each of the instances individually. Like so
Code:
var listSize = ds_list_size(obj_components.list_pushables)
for(var i = 0, i < listSize, ++i)
{
currentInstance = ds_list_find_value(list_pushables, i)
with (currentInstance)
{
code here
}
}
Obviously, GM's built-in parent/child stuff is still very useful, especially when you want to use its built-in functions with parents like place_meeting(x, y, par_impassable).
Is that all there is to it? Am I forgetting something obvious, or does that capture most of the power of parent/child inheritance but allow for multi-inheritance?