PDA

View Full Version : OOP ideas



ErosOlmi
23-08-2013, 23:23
All started from this post :D

http://www.thinbasic.com/community/showthread.php?t=12196

Charles Pegge
24-08-2013, 09:03
Hi Eros,

This is nearly OOP. You have dialog objects, with their own shared variables, and methods for dealing with dialog events.

It will only take one or two steps further to create a generic OOP system :)

ReneMiner
24-08-2013, 10:09
Great. I instantly copied the script into thinAir and tried to run it - of course did not work... :D :D :D
- I was not really awake - it was 6:00 in the morning...

The "Dialog scope" probably can be achieved by some "Super-Function" with some Begin-End-Closure which is a combination of Type + Functions. Comes very close to oop...

"Unit" is not a final suggest but some placeholder for something that does not exist yet but which makes easier to understand what I mean.
Maybe replace it with "TBClass" ?



Unit someUnit

xxx As Long ' would be a subset to this Super-function and "somewhat local" to it

' "usual" function within the "Super-Function":
Function abc(yyy as Long) As Long

Function = Me.xxx + yyy

End Function

End Unit
'...

[Create Unit] blueUnit [= New/ As] someUnit ' don't care if "Dim", "= New" or "As"
[Create Unit] greenUnit [= New/ As] someUnit



So it will just create an Udt - or is it an object? - somewhat "equal" to this:



Type someUnit
xxx As Long
Static abc As Function Ptr ' probably contains a function-pointer?
End Type

Dim blueUnit as someUnit
Dim greenUnit as someUnit


It needs some Keyword oop-alike "This" or vb-alike "Me" as an alias for the name used on "Create Unit" from within the units functions that holds the pointer to current "udt-element", which can be achieved from outside the Super-Function using for example "greenUnit.xxx = 123"
When Functions within the Super-Function get called like


if blueUnit.abc(123) Then

it should set the Value "Me" to the pointer of blueUnits variables (could it therefor need some special stack?) and just call Function at Ptr abc.
Probably such Super-Function must not contain dynamic Arrays because of this and the close relation to "Type" - but Functions within it would work as usual and allow local dynamic arrays.
Calling the Function just by its name alike "abc(123)" could probably be posible too - but not change the Pointer in "Me" in advance - so if calls occur within the same unit, "Me" anyway contains the correct pointer if the very first call was correct - so no need to set it - and programmers are responsible for what they're doing.

If that would work, the way to use it for "Dialog-scope" also were free - but perhaps I'm on totally wrong track - and it's not as easy as it seems.

It should also allow to do something like this:


Create Unit redUnit(5) As someUnit

so one could create an "array" of objects - especially useful when working with multiple documents each in its own dialog - but current ControlID-approach probably would not work using constants - since one can not write "redUnit(1).%IDC_Timer" it would need something alike


Me.IDC_Timer = CONTROL GetFreeID

- but probably the controls get names instead of indexes too, so ...

It's not really a "local scope" - I know... should be enough for now- maybe contains some idea.

ReneMiner
25-08-2013, 09:03
Something else - more to the callbacks- I noticed there's no "syscommand" yet. In vb6 they don't have Minimize/Maximize/Restore-Events but they fire off a Resize-Event which includes probably the known %WM_Size-event.

The form (dialog) has some WindowState-Property which can be either vb_Normal, vb_Minimized or vb_Maximized and one has to read out the value there. So there's no "On_Minimize" etc.

I don't know how familiar you are with vb - especially version previous vb.net, i.e. visual basic 6.0. If tB would have a little of this (visual designer + automatic generated events when a control gets drawn onto the dialog) - which makes it pretty easy to get visible results in no time flat I would love it and there are probably a few more users who also don't like the vb.net-way which is no real basic any more but just some .net-Framework-managed language. The only thing that's close to vb6 is basic for android - but there's no more such thing for windows. ThinBasic already offers a whole lot more controls built into UI than vb6 ever came with - of course there are user-definded + extension-controls but they don't count...

Since Visual Designer is still in some experimental or unfinished state I think it would be possible to be inspired a little by vb6 - but don't look at vb.net! Best to run it in SDI-mode (Extras/Options) because gives more feeling of artistic freedom. TB-UI already has so many "hidden" features and I think it would be a whole lot easier and faster to develop TB-UI-stuff if Controls and Dialogs would have Names, Properties, Functions & Events.
Also - as you already discoverd would be useful - every Dialog (form) has it's "own" variable-scope that get accessed for example alike "myDialog(1).myVar = 123" - it works the same way with Properties "if myDialog(1).WindowState = vb_Minimized Then..." etc.
The functions/subs "attached" to some Dialog are by default Private to the Dialog - but can be declared Public too - and each Dialog has its own "code-unit-file" + some extra "form-file" which does just the layout.
To access a dialogs (public) function one has to "prefix" the subs name with the dialogs name alike "Call myDialog(1).Draw()" - so each Dialog can have it's own "Draw"-sub... - and not just if the Dialogs use the same kind of window / are of the same class. Also each Dialog can have it's own btn_OK ("myDialog(2).btn_OK.Enabled = True") - even indexed controls (that have to be of same type)
Since vb6 is not supported (win98 SE/2000-standard) any more and only runs very limited on 64bit-machines while vb.net is already cumbersome and intransparent to use and no real basic in my eyes, there's a big gap on the "windows-market" that none has filled yet to my satisfaction. "UI" already has the controls+dialogs available - but their handling...very time-consumpting and always some obstacle for example if one want's to change something in Dialog-Layout

...maybe you already know

Petr Schreiber
25-08-2013, 09:19
I like the proposed approach a lot,

I think some kind of namespace would be needed to do the same for controls, because many dialogs will have OK/Cancel button for example. Or we could pick DialogName_ControlName_Event naming convention.
What would be essential is to document those events completely - as was noted in other thread, browsing MSDN is not user friendly for people without prior Win32 experience - and there will be less and less with it, because "Visual" languages always wrap it.

Full OOP in TB would be perfect, I would not hesitate to carbon copy it from .NET :P, but that is project for some years. (It is similar to VB as Rene proposed, but more polished).


Petr

Charles Pegge
25-08-2013, 10:14
I think the most important part of OOP is for objects (or UDTs) being able to call their own functions and use shared variables confined within the scope of each object. Everything else is bells and whistles that can be added later.

ReneMiner
26-08-2013, 08:18
maybe just as simple as this:



Uses "console"

Type pseudoclass
someVar As Long
Static abc As String
End Type


Function abc( ByVal xxx As Long ) As Long
Return xxx * 2 + THIS.someVar ' does not throw Error but just gets interpreted as 0
End Function


Dim myClass(3) As pseudoclass
myClass(1).abc = "abc"

myClass(1).someVar = 1000 ' this does not get added in result yet :(
myClass(2).someVar = 2000

Long lResult

Call myClass(2).abc (21) To lResult

PrintL lResult

WaitKey

If the Call-Keyword (or some "replacement" as Call_IfExists) now would just set some "system-global" as "THIS" to point at element 2 of my class, the function could calculate using someVar which belongs to current element. I think a stack would be needed therefor - and just a virtual overlay probably won't work since if THIS is once declared as pseudoclass it can not change type.
If THIS is not possible because of complications to await in future, it could be just replaced with ME.
But because the Funtion is not within the "Type" it does not know anyway what THIS is...

Petr Schreiber
26-08-2013, 08:42
Interesting,

what about this modification - UDT could be used to call every function, which takes such an UDT as first parameter (yes, we are getting off the track a bit :D):


TYPE MyData
a AS LONG
b AS STRING
END TYPE

FUNCTION MyFunction( data AS MyData, x AS LONG, y AS LONG)
data.a = x + y
data.b = Format$(data.a)
END FUNCTION

FUNCTION ReturnAPlus2(data AS MyData) AS LONG
RETURN data.a + 2
END FUNCTION

DIM o AS MyData

o.MyFunction(2, 3) ' -- This passes the o as first parameter automagically

MSGBOX 0, o.a ' -- 6
MSGBOX 0, o.b ' -- "6"

MSGBOX 0, o.ReturnAPlus2() ' -- This passes the o as first parameter automagically, so no more are needed - value 8 would be displayed in this case




Petr

ReneMiner
26-08-2013, 09:44
That approach EDIT: ALONE would not allow each Udt (later Dialog) to have its own "Draw()"-Function i fear, since it might have different subsets (later controls)
- so won't make sense to pass the Udt to a function that only can work with one type...

Petr Schreiber
26-08-2013, 09:47
This is basically the approach used in Python - you pass self(=this, =me) parameter as first. With concept of isolated units/scope, it would work okay, otherwise it would cause the name conflicts as you say.


Petr

ReneMiner
26-08-2013, 10:23
I rewrote it a little bit using two different "classes" with two functions that have the "same name" (___.abc) at user-side.



' This script actually runs.
Uses "console"

' -------------------------------------------
'Begin Class 1

Type pseudoclass1
someVar As Long
Static abc As DWord '= Function_GetPtr(abc1)
End Type
Function abc1(ByVal pData As DWord, ByVal xxx As Long ) As Long
' this one awaits pointer

Local ME As pseudoclass1 At pData

Return xxx * 2 + ME.someVar - 1000

End Function

'End Class 1
' -------------------------------------------

Dim myObject1 As pseudoclass1

' have to set this manually here:
myObject1.abc = Function_GetPtr(abc1)

' -------------------------------------------
'Begin Class 2

Type pseudoclass2
otherVar As Long
Static abc As DWord ' = Function_GetPtr(abc2)
End Type
Function abc2( ByRef ME As pseudoclass2, ByVal xxx As Long ) As Long
' different approach to determine ME here...probably no good for nested types...

Return xxx * 2 + ME.otherVar - 2000

End Function

'End Class 2
' -------------------------------------------

Dim myObject2(3) As pseudoclass2
myObject2(1).abc = Function_GetPtr(abc2)

' Test
Long lResult
myObject1.someVar = 1000
myObject2(2).otherVar = 2000

Call myObject1.abc (VarPtr myObject1, 21) To lResult
PrintL lResult

Call_IfExists myObject2(2).abc ( myObject2(2), 21) To lResult
PrintL lResult

WaitKey

Now only needs some Begin-End-Closure around - so the Functions get embedded into the "Type" and the pointer gets set immediately (static the same to all objects of this "class" )
- and of course something that informs the "embedded" function which element of the Type currently to work with ("ME/THIS") would be better than to have pass always the var byref or its pointer.

Perhaps can be achieved through a different behavior of Call when passed function-ptr is part of "class"-structure - so identified as "method" -or even proceeding such without keyword "call"

ReneMiner
26-08-2013, 19:46
Getting fresh:



' This script does not run - yet...but equals the above

Uses "console"

' -------------------------------------------
CLASS Class1

someVar As Long
METHOD abc( ByVal xxx As Long ) As Long

Return xxx * 2 + THIS.someVar - 1000

End METHOD

End CLASS
' -------------------------------------------
New myObject1 As Class1

' -------------------------------------------
CLASS Class2

otherVar As Long
METHOD abc( ByVal xxx As Long ) As Long

METHOD = xxx * 2 + THIS.otherVar - 2000

End METHOD

End CLASS
' -------------------------------------------
Dim myObject2(3) As New Class2 ' maybe DIM also would serve?

' -------------------------------------------
' Test
Long lResult
myObject1.someVar = 1000
myObject2(2).otherVar = 2000

lResult = myObject1.abc(21)
PrintL lResult

lResult = myObject2(2).abc(21)
PrintL lResult

WaitKey

...awaiting comments :unsure:

Petr Schreiber
26-08-2013, 20:08
Hi Rene,

I like the approach in second post more - intuitive, no pointer struggle :)


Petr

ErosOlmi
26-08-2013, 20:26
Wow: you guys are great!
Great ideas, great suggestions, great thoughts ... BUT ...

sorry, I was not talking about OOP here but just about another optional ways to handle DIALOGs CALLBACKs events and, if working fine, possibly extend to CONTROLs events.
Just that.

I'm really fascinated by all your ideas on OOP but this is not the post, sorry :oops:

OOP is something I would really love to have in thinBasic but something not just around the corner, something for the next months maybe.

So, do not worry and keep going on on this brain-storming, all ideas will be useful at the right time.

Ciao
Eros

PS: maybe I will split first post from the others changing subject.