Equivalent of classes in LiveCode

LiveCode is the premier environment for creating multi-platform solutions for all major operating systems - Windows, Mac OS X, Linux, the Web, Server environments and Mobile platforms. Brand new to LiveCode? Welcome!

Moderators: Klaus, FourthWorld, heatherlaine, kevinmiller, robinmiller

Post Reply
mwieder
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 3202
Joined: Mon Jan 22, 2007 7:36 am
Location: Berkeley, CA, US
Contact:

Re: Equivalent of classes in LiveCode

Post by mwieder » Tue Aug 18, 2020 5:17 am

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.

bwmilby
Posts: 356
Joined: Wed Jun 07, 2017 5:37 am
Location: Henrico, VA
Contact:

Re: Equivalent of classes in LiveCode

Post by bwmilby » Wed Aug 19, 2020 4:57 am

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:

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
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.
Brian Milby

Script Tracker https://github.com/bwmilby/scriptTracker

rkriesel
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 89
Joined: Thu Apr 13, 2006 6:25 pm

Re: Equivalent of classes in LiveCode

Post by rkriesel » Wed Aug 19, 2020 9:04 am

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

aetaylorBUSBnWt
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 57
Joined: Thu Sep 20, 2012 5:11 pm

Re: Equivalent of classes in LiveCode

Post by aetaylorBUSBnWt » Wed Aug 19, 2020 9:31 pm

mwieder wrote:
Tue Aug 18, 2020 5:17 am
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.
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.

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(....)

aetaylorBUSBnWt
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 57
Joined: Thu Sep 20, 2012 5:11 pm

Re: Equivalent of classes in LiveCode

Post by aetaylorBUSBnWt » Wed Aug 19, 2020 9:33 pm

bwmilby wrote:
Wed Aug 19, 2020 4:57 am
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:

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
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.
HI,
Doesn't this require that in each super class that the "constructor" method actually be named:

className.constructor

??

bwmilby
Posts: 356
Joined: Wed Jun 07, 2017 5:37 am
Location: Henrico, VA
Contact:

Re: Equivalent of classes in LiveCode

Post by bwmilby » Thu Aug 20, 2020 3:45 am

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).
Brian Milby

Script Tracker https://github.com/bwmilby/scriptTracker

mwieder
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 3202
Joined: Mon Jan 22, 2007 7:36 am
Location: Berkeley, CA, US
Contact:

Re: Equivalent of classes in LiveCode

Post by mwieder » Thu Aug 20, 2020 7:41 pm

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.
Attachments
OOPMWLivecode.zip
(90.45 KiB) Downloaded 36 times

aetaylorBUSBnWt
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 57
Joined: Thu Sep 20, 2012 5:11 pm

Re: Equivalent of classes in LiveCode

Post by aetaylorBUSBnWt » Fri Aug 21, 2020 7:05 pm

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

bwmilby
Posts: 356
Joined: Wed Jun 07, 2017 5:37 am
Location: Henrico, VA
Contact:

Re: Equivalent of classes in LiveCode

Post by bwmilby » Fri Aug 21, 2020 7:28 pm

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.
Brian Milby

Script Tracker https://github.com/bwmilby/scriptTracker

mwieder
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 3202
Joined: Mon Jan 22, 2007 7:36 am
Location: Berkeley, CA, US
Contact:

Re: Equivalent of classes in LiveCode

Post by mwieder » Fri Aug 21, 2020 8:09 pm

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

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
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?

mwieder
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 3202
Joined: Mon Jan 22, 2007 7:36 am
Location: Berkeley, CA, US
Contact:

Re: Equivalent of classes in LiveCode

Post by mwieder » Fri Aug 21, 2020 8:11 pm

...and you don't actually need to create the list beforehand, although I like your method better than my original recursive method.

bwmilby
Posts: 356
Joined: Wed Jun 07, 2017 5:37 am
Location: Henrico, VA
Contact:

Re: Equivalent of classes in LiveCode

Post by bwmilby » Fri Aug 21, 2020 9:28 pm

ClassVehicle

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
ClassCar - no code - behavior is ClassVehicle

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
SetYellow

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 "SetRed"
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
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.
Brian Milby

Script Tracker https://github.com/bwmilby/scriptTracker

bwmilby
Posts: 356
Joined: Wed Jun 07, 2017 5:37 am
Location: Henrico, VA
Contact:

Re: Equivalent of classes in LiveCode

Post by bwmilby » Fri Aug 21, 2020 9:31 pm

mwieder wrote:
Fri Aug 21, 2020 8:11 pm
...and you don't actually need to create the list beforehand, although I like your method better than my original recursive method.
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

aetaylorBUSBnWt
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 57
Joined: Thu Sep 20, 2012 5:11 pm

Re: Equivalent of classes in LiveCode

Post by aetaylorBUSBnWt » Fri Aug 21, 2020 10:41 pm

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.

mwieder
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 3202
Joined: Mon Jan 22, 2007 7:36 am
Location: Berkeley, CA, US
Contact:

Re: Equivalent of classes in LiveCode

Post by mwieder » Fri Aug 21, 2020 10:55 pm

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".

Post Reply

Return to “Getting Started with LiveCode - Experienced Developers”