Equivalent of classes in LiveCode
Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller
-
- VIP Livecode Opensource Backer
- Posts: 3581
- Joined: Mon Jan 22, 2007 7:36 am
- Location: Berkeley, CA, US
- Contact:
Re: Equivalent of classes in LiveCode
Brian-
I'm sure you're right about the superClass command. That's a relic of some earlier experimenting and I'm not using it anywhere.
Much the same for the setClassForControl command. It was in Hakan's original code, so I didn't feel I should delete the command, although I don't think it properly belongs in an OOP context.
You're partially right about the destructor code. The destructor is properly being called, but the "die" command is failing because in one case the object has already been deleted by the animate code in the Emittor button, and in the other it's not kosher to have an object delete itself while its code is still executing.
The instance variables of the various classes are not tied to the abstract class but to what I think of as local shadow backscripts of the instantiated objects. Otherwise the dx/dy variables for the individual particles would all be the same.
And moving away from groups was because the original intention of the groups was to create copies of the abstract classes on the Classes card, which is no longer necessary, as you noted, with behaviors. Creating a button in the newObject code just fell out from that exercise, and there's no reason why it needs to be limited to a button. The newObject command could easily take a control type as an argument, and probably should.
But I hope you're not thinking of "multiple inheritance" in a way that is different from serial inheritance. That way lies madness.
...and I would *love* to have dot notation to work with here, but there's absolutely no chance of getting that integrated into the language.
I'm sure you're right about the superClass command. That's a relic of some earlier experimenting and I'm not using it anywhere.
Much the same for the setClassForControl command. It was in Hakan's original code, so I didn't feel I should delete the command, although I don't think it properly belongs in an OOP context.
You're partially right about the destructor code. The destructor is properly being called, but the "die" command is failing because in one case the object has already been deleted by the animate code in the Emittor button, and in the other it's not kosher to have an object delete itself while its code is still executing.
The instance variables of the various classes are not tied to the abstract class but to what I think of as local shadow backscripts of the instantiated objects. Otherwise the dx/dy variables for the individual particles would all be the same.
And moving away from groups was because the original intention of the groups was to create copies of the abstract classes on the Classes card, which is no longer necessary, as you noted, with behaviors. Creating a button in the newObject code just fell out from that exercise, and there's no reason why it needs to be limited to a button. The newObject command could easily take a control type as an argument, and probably should.
But I hope you're not thinking of "multiple inheritance" in a way that is different from serial inheritance. That way lies madness.
...and I would *love* to have dot notation to work with here, but there's absolutely no chance of getting that integrated into the language.
PowerDebug http://powerdebug.ahsoftware.net
PowerTools http://www.ahsoftware.net/PowerTools/PowerTools.irev
PowerTools http://www.ahsoftware.net/PowerTools/PowerTools.irev
Re: Equivalent of classes in LiveCode
Actually, I was thinking about simulating dot notation and not putting it into the engine. We would define another class called "object" that would be the parent of everything. Here is the one method that I would have in it so far:
Then we would define "particle.constructor", "gravityParticle.constructor" and so on. While you still end up with one dispatch per class in the hierarchy, this method is more robust because a skipped level wouldn't break it. It also eliminates the conditionals in every dispatch and recursion that was in the other implementation. Lastly, it removes just about all of the implementation of the ordering from the individual class definitions and replaces that with a naming convention for the constructor.
Code: Select all
command constructor
local tClass, tClassList
put the behavior of me into tClass
repeat while tClass is not empty
put the short name of tClass & lf before tClassList
put the behavior of tClass into tClass
end repeat
delete the last char of tClassList
if line 1 of tClassList is "object" then
delete line 1 of tClassList
end if
repeat for each line tClass in tClassList
dispatch tClass & ".constructor" to me
end repeat
end constructor
Brian Milby
Script Tracker https://github.com/bwmilby/scriptTracker
Script Tracker https://github.com/bwmilby/scriptTracker
Re: Equivalent of classes in LiveCode
Hi, Brian. I like your ".constructor" suggestion for ease of understanding the action.
Why exclude "object.constructor" from the action? It could take some of the code from newObject. Or if "object.constructor" doesn't exist, the unhandled dispatch would be harmless.
Thanks for sharing your insight.
-- Dick
Why exclude "object.constructor" from the action? It could take some of the code from newObject. Or if "object.constructor" doesn't exist, the unhandled dispatch would be harmless.
Thanks for sharing your insight.
-- Dick
-
- VIP Livecode Opensource Backer
- Posts: 118
- Joined: Thu Sep 20, 2012 5:11 pm
Re: Equivalent of classes in LiveCode
So far I am finding that in order to have access to superClass methods (a behavior's functions) with the variables of the actual object I want to work with, I need to explicitly get that object to the superClass method.mwieder wrote: ↑Tue Aug 18, 2020 5:17 amBrian-
I'm sure you're right about the superClass command. That's a relic of some earlier experimenting and I'm not using it anywhere.
Much the same for the setClassForControl command. It was in Hakan's original code, so I didn't feel I should delete the command, although I don't think it properly belongs in an OOP context.
So for example in the addressingBehaviorsChangesTarget example there is the "reportBehav" command.
I have modified the buttons in the bottom-most level to have a ''reportBehav" command, that do stuff and then call the superClass.
The only way to keep the same "object' is to pass it as a parameter to the superClass:
on reportBehav
----do stuff at this level of the class hierarchy.....
dispatch "reportBehav" to the behavior of me with target
or
dispatch "reportBehav" to the behavior of me with long id of me
....and I can do more stuff after the superClass returns....
end reportBehav
and then the next level up class's method must check for the existence of that parameter and react accordingly.
any superclass up the chain must expect to have to handle the object id since LiveCode's syntax is not thinking of class/object hierarchy.
on reportBehav pid
if pid is not empty then
put "from Behav1" & cr & "Target: " & the target & cr & "Name of pid: " & the name of pid & cr & "this me: " & the name of this me & cr & the milliseconds & cr into field 1
else
put "from Behav1" & cr & "Target: " & the target & cr & "Name of me: " & the name of me & cr & "this me: " & the name of this me & cr & the milliseconds into field 1
end if
end reportBehav
But having to write 2 different handlers like the above is madness because the second one is accessing the behavior's script locals which have nothing to do with the object that I really want to work with. But the above code does show that if you don't supply "pid" what you want is not going to happen.
Net result, for consistency, the object ID always needs to be passed and used.
on reportBehav pid
if pid is not empty then
put "from Behav1" & cr & "Target: " & the target & cr & "Name of pid: " & the name of pid & cr & "this me: " & the name of this me & cr & the milliseconds & cr into field 1
else
throw "Behav1 reportBehav method called without object ID"
end if
end reportBehav
By the way, this is actually what is going on behind the scenes in C++.
At a certain level you can think of C++ as just plain old C functions that always have a pointer to a structure as the first parameter. That structure contains the variables that the function is going to operate on.
In C++ if you want to get at the super class's method explicitly you put in super->methodName(....).
While it is more typing, that is what "to the behavior of me with target" is all about.
ie.
dispatch "reportBehav" to the behavior of me with target
Possibly there is a way to set up something that lets one type:
dispatch "reportBehav" to SUPER
and have SUPER replaced with "the behavior of me with target" and still have LiveCode interpret it properly without taking a massive real time processing hit when the program is running?
Ultimately one would also want to explicitly state a particular level in the class hierarchy you want to get to, which in C++ would be:
superClassName::methodName(....)
-
- VIP Livecode Opensource Backer
- Posts: 118
- Joined: Thu Sep 20, 2012 5:11 pm
Re: Equivalent of classes in LiveCode
HI,bwmilby wrote: ↑Wed Aug 19, 2020 4:57 amActually, I was thinking about simulating dot notation and not putting it into the engine. We would define another class called "object" that would be the parent of everything. Here is the one method that I would have in it so far:
Then we would define "particle.constructor", "gravityParticle.constructor" and so on. While you still end up with one dispatch per class in the hierarchy, this method is more robust because a skipped level wouldn't break it. It also eliminates the conditionals in every dispatch and recursion that was in the other implementation. Lastly, it removes just about all of the implementation of the ordering from the individual class definitions and replaces that with a naming convention for the constructor.Code: Select all
command constructor local tClass, tClassList put the behavior of me into tClass repeat while tClass is not empty put the short name of tClass & lf before tClassList put the behavior of tClass into tClass end repeat delete the last char of tClassList if line 1 of tClassList is "object" then delete line 1 of tClassList end if repeat for each line tClass in tClassList dispatch tClass & ".constructor" to me end repeat end constructor
Doesn't this require that in each super class that the "constructor" method actually be named:
className.constructor
??
Re: Equivalent of classes in LiveCode
Yes, it would require the contractor to be named with the class prefix. This is specifically to allow calling the constructors in the correct order. It is far less code than the other option that I included earlier (which breaks if a class does not have a constructor and ones above do).
Your method would mean that each class has to maintain the state for each instance manually. You would also only be using the behavior as a holder for the (super)class since dispatches are done manually (to the object and not the instance).
Your method would mean that each class has to maintain the state for each instance manually. You would also only be using the behavior as a holder for the (super)class since dispatches are done manually (to the object and not the instance).
Brian Milby
Script Tracker https://github.com/bwmilby/scriptTracker
Script Tracker https://github.com/bwmilby/scriptTracker
-
- VIP Livecode Opensource Backer
- Posts: 3581
- Joined: Mon Jan 22, 2007 7:36 am
- Location: Berkeley, CA, US
- Contact:
Re: Equivalent of classes in LiveCode
Brian- I like your idea of constructing the behavior list for the constructors. But note that you don't need a separate Object class or a dot notation naming convention for this.
I incorporated the list into the newObject handler to invoke the class constructors on object creation and it's working.
So here's my v1.02 of the OOP library (which could easily be a script-only stack) and the Particles demo.
The newObject command now also takes an option type argument which defaults to "button". It leads to a handful of private object creator handlers because the "create" or "new" command in LiveCode doesn't take an expression as an argument. I'm working on a pull request for that, but without a chance of it ever getting accepted.
I incorporated the list into the newObject handler to invoke the class constructors on object creation and it's working.
So here's my v1.02 of the OOP library (which could easily be a script-only stack) and the Particles demo.
The newObject command now also takes an option type argument which defaults to "button". It leads to a handful of private object creator handlers because the "create" or "new" command in LiveCode doesn't take an expression as an argument. I'm working on a pull request for that, but without a chance of it ever getting accepted.
- Attachments
-
- OOPMWLivecode.zip
- (90.45 KiB) Downloaded 162 times
PowerDebug http://powerdebug.ahsoftware.net
PowerTools http://www.ahsoftware.net/PowerTools/PowerTools.irev
PowerTools http://www.ahsoftware.net/PowerTools/PowerTools.irev
-
- VIP Livecode Opensource Backer
- Posts: 118
- Joined: Thu Sep 20, 2012 5:11 pm
Re: Equivalent of classes in LiveCode
Hi,
I am thinking that the primary users of a library such as this are going to be C++ converts, people still using C++.
So why not name the Constructor method the name of the class itself like C++ (and Objective C) do?
I suppose using "constructor" means simpler code in the dispatch process.
In addition, the way the dispatch in "invokeConstructorsOf" is done, each tClass is operating on different data.
Doesn't it need to be:
dispatch "constructor" to tClass with pObject
Andrew
I am thinking that the primary users of a library such as this are going to be C++ converts, people still using C++.
So why not name the Constructor method the name of the class itself like C++ (and Objective C) do?
I suppose using "constructor" means simpler code in the dispatch process.
In addition, the way the dispatch in "invokeConstructorsOf" is done, each tClass is operating on different data.
Doesn't it need to be:
dispatch "constructor" to tClass with pObject
Andrew
Re: Equivalent of classes in LiveCode
Naming the constructor the same as the class solves all of the issues I was trying to address with the constructor dot notation. Since I don’t write C++ code (except when I make minor changes in the engine), I didn’t realize this. You still need to build the list to do it in the correct order unless you assume that every class must have a constructor (which is probably a good convention).
I don’t think the dispatch with model really works though. That removes the capability of using script local variables to maintain state of a class object and puts all of the effort on the developer to code it using shared variable(s). It also means that you can’t use the normal message path or you will not have access to the correct state data.
I don’t think the dispatch with model really works though. That removes the capability of using script local variables to maintain state of a class object and puts all of the effort on the developer to code it using shared variable(s). It also means that you can’t use the normal message path or you will not have access to the correct state data.
Brian Milby
Script Tracker https://github.com/bwmilby/scriptTracker
Script Tracker https://github.com/bwmilby/scriptTracker
-
- VIP Livecode Opensource Backer
- Posts: 3581
- Joined: Mon Jan 22, 2007 7:36 am
- Location: Berkeley, CA, US
- Contact:
Re: Equivalent of classes in LiveCode
I've got no problem with naming the constructor with the class name. It's a one-line change to the OOP script, changing it to
Unfortunately, though, there's no way to name the destructor similarly to ~Classname. The script parser barfs.
Brian-
not sure what you're referring to as a problem with the dispatch model. Classes are abstract and have no instantiated variables.
Can you give me an example of what you see as a problem?
Code: Select all
# call the class constructors in order
repeat for each line tClass in tClassList
dispatch the short name of tClass to tClass
end repeat
Brian-
not sure what you're referring to as a problem with the dispatch model. Classes are abstract and have no instantiated variables.
Can you give me an example of what you see as a problem?
PowerDebug http://powerdebug.ahsoftware.net
PowerTools http://www.ahsoftware.net/PowerTools/PowerTools.irev
PowerTools http://www.ahsoftware.net/PowerTools/PowerTools.irev
-
- VIP Livecode Opensource Backer
- Posts: 3581
- Joined: Mon Jan 22, 2007 7:36 am
- Location: Berkeley, CA, US
- Contact:
Re: Equivalent of classes in LiveCode
...and you don't actually need to create the list beforehand, although I like your method better than my original recursive method.
PowerDebug http://powerdebug.ahsoftware.net
PowerTools http://www.ahsoftware.net/PowerTools/PowerTools.irev
PowerTools http://www.ahsoftware.net/PowerTools/PowerTools.irev
Re: Equivalent of classes in LiveCode
ClassVehicle
ClassCar - no code - behavior is ClassVehicle
CarObject1 - no code - behavior is ClassCar
CarObject2 - no code - behavior is ClassCar
SetRed
SetYellow
Click on "SetRed"
Click on "SetYellow"
Click on "CarObject1"
Click on "CarObject2"
Click on "ClassCar"
Log (read bottom up):
I could make this work by passing the object as a parameter and keeping track manually, but that seems to defeat the purpose of the OOPEngine.
Code: Select all
local sColor
function getColor
return sColor
end getColor
command setColor pColor
put pColor into sColor
end setColor
on mouseUp
dispatch function "getColor" to the behavior of me
put the result into tColor1
dispatch function "getColor" to me
put the result into tColor2
put the short name of the behavior of me && tColor1 &&\
the short name of me && tColor2 & lf before field "log"
end mouseUp
CarObject1 - no code - behavior is ClassCar
CarObject2 - no code - behavior is ClassCar
SetRed
Code: Select all
on mouseup
put "CarObject1 set to Red" & lf before field "log"
dispatch "setColor" to the behavior of button "CarObject1" with "Red"
end mouseup
Code: Select all
on mouseup
put "CarObject2 set to Yellow" & lf before field "log"
dispatch "setColor" to the behavior of button "CarObject2" with "Yellow"
end mouseup
Click on "SetYellow"
Click on "CarObject1"
Click on "CarObject2"
Click on "ClassCar"
Log (read bottom up):
Code: Select all
ClassVehicle ClassCar Yellow
ClassCar Yellow CarObject2
ClassCar Yellow CarObject1
CarObject2 set to Yellow
CarObject1 set to Red
Brian Milby
Script Tracker https://github.com/bwmilby/scriptTracker
Script Tracker https://github.com/bwmilby/scriptTracker
Re: Equivalent of classes in LiveCode
Correct. I was not precise, but that is what I was thinking. You can't use a recursive method unless you assume there are no missing constructors.
Brian Milby
Script Tracker https://github.com/bwmilby/scriptTracker
Script Tracker https://github.com/bwmilby/scriptTracker
-
- VIP Livecode Opensource Backer
- Posts: 118
- Joined: Thu Sep 20, 2012 5:11 pm
Re: Equivalent of classes in LiveCode
Hi,
Just applied the 1.02 OOPengine with the "short name" mod for the constructor to code I am using.
I used the "default" object type for the newObject function call - so button.
That is appropriate when you want a new UI object to show up on the screen - which is the thought process in LiveCode - very little does not show up on the screen.
For a C++ programmer, the response is ACK!
So when I want to create a behind the scenes, never ever gonna be seen object - what should I be specifying for the object?
And that, IMHO, should be the default object.
Just applied the 1.02 OOPengine with the "short name" mod for the constructor to code I am using.
I used the "default" object type for the newObject function call - so button.
That is appropriate when you want a new UI object to show up on the screen - which is the thought process in LiveCode - very little does not show up on the screen.
For a C++ programmer, the response is ACK!
So when I want to create a behind the scenes, never ever gonna be seen object - what should I be specifying for the object?
And that, IMHO, should be the default object.
-
- VIP Livecode Opensource Backer
- Posts: 3581
- Joined: Mon Jan 22, 2007 7:36 am
- Location: Berkeley, CA, US
- Contact:
Re: Equivalent of classes in LiveCode
I made the default object a button only in order to make minimal changes to the Particles stack.
It should rightly be a group, and the Particles stack should have its newObject calls have a third argument of "button".
It should rightly be a group, and the Particles stack should have its newObject calls have a third argument of "button".
PowerDebug http://powerdebug.ahsoftware.net
PowerTools http://www.ahsoftware.net/PowerTools/PowerTools.irev
PowerTools http://www.ahsoftware.net/PowerTools/PowerTools.irev