Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Methods in types
#1
I apologize if this has been discussed before, a search of the forum was a bit inconclusive. I much prefer working in QBPE but I recently did a couple projects in FreeBASIC because FreeBASIC allows having methods in UDTs, which was very advantageous to writing the solutions. How difficult would it be to add the capability to include methods with a TYPE definition in QBPE? TIA
It's not the having, it's the doing.
Reply
#2
You're talking about classes? A class is a udt that can have member functions.

Classes work by having a hidden extra parameter for member functions, a "this" pointer. That way, the member function knows which object it is working on.

A similar effect can be had in procedural languages by adding the extra parameter yourself. This is similar to what the win32 api does using handles, implementing object orientation using a procedural interface.

Here is a simple, but not practical, example in qbasic 1.1:

Code: (Select All)
DECLARE SUB DrawCritter (this AS ANY)
DECLARE SUB EraseCritter (this AS ANY)
DECLARE SUB IterateCritter (this AS ANY)
DECLARE SUB CloseCritter (this AS ANY)
DECLARE SUB CreateCritter (this AS ANY)

TYPE critter
l AS INTEGER
c AS INTEGER
age AS INTEGER
letter AS INTEGER
END TYPE

CLS
DIM crit AS critter
CreateCritter crit
WHILE crit.age < &H10
EraseCritter crit
IterateCritter crit
DrawCritter crit
SLEEP 1
WEND
CloseCritter crit
SYSTEM

SUB CloseCritter (this AS critter)
this.l = 0
this.c = 0
this.age = 0
this.letter = 0
END SUB

SUB CreateCritter (this AS critter)
this.l = INT(RND * 25) + 1
this.c = INT(RND * 80) + 1
this.age = 1
this.letter = INT(RND * 26) + &H61
END SUB

SUB DrawCritter (this AS critter)
LOCATE this.l, this.c
COLOR this.age AND &HF, 0
PRINT CHR$(this.letter);
END SUB

SUB EraseCritter (this AS critter)
LOCATE this.l, this.c
COLOR 7, 0
PRINT " ";
END SUB

SUB IterateCritter (this AS critter)
this.l = this.l + INT(RND * 3) - 1
this.c = this.c + INT(RND * 3) - 1
IF this.l < 1 THEN this.l = 1
IF this.l > 25 THEN this.l = 25
IF this.c < 1 THEN this.c = 1
IF this.c > 80 THEN this.c = 80
this.age = this.age + 1
END SUB

One of the problems with doing this in qbasic 1.1 is a lack of proper pointer support. Yeah, qbasic has varptr, peek, and poke, but it doesn't have proper typed pointer support in the language.

To be practical, you would have to use an array, and manage the allocation within the array manually. In qb64, you could use _mem blocks.

Another consideration, if you're accustomed to c++, is that c++ will manage object lifetime automatically for you, calling it "resource allocation is initialization". C++ will automatically call the constructors and destructors for you. In particular, the destructor is called whenever the scope is exited, whether by a return, by an end of block, or by an exception. In qbasic, you would have to do all of that manually.

The win32 api uses handle counts. So, calling CloseHandle on an object decrements a handle counter. Only when the last handle is closed is the object actually destroyed.

All of the above applies to implementing oop within a procedural language. As for modifying qb64 to accommodate classes, i don't know. Obviously, it would need to involve a hidden "this" pointer. And it would probably need to involve implementing raii by calling constructors and destructors automatically. Since qb64 translates to c++, it might be possible to use c++'s own raii for this, but i don't know.
Reply
#3
this would just create an impressive mess that many people really wouldn't want to deal with.  it would not attract more people to qb64 phoenix more than actually.  oop is advocated a lot but outside c++ and python, the response becomes more feeble every year.  hype about haskell and rust and others makes it more so.

i wanted to like julia.  but almost everything i could imagine doing in that language, i could do in lua easily.  if not i don't mind using qb64 but having to recompile into binary sucks with each minor adjustment.

one thing that i like about oop.  is the ability to overload subprograms and functions.  freebasic could do that if i'm not mistaken without even using the extended type... end type syntax.  a long time ago they promised a proper "class" keyword.  they would have to keep up with developments in c++.

if you don't like executable files much larger than the typical 1-1/2 mib that qb64 phoenix could create today for a "hello, world" program.  then it becomes repulsive to have inheritance, methods and overloading.  a great many programs have been written already, not just with c, which never needed oop.  simply because it has to be as small and efficient as possible.  it could be murder to a hobbyist.  take it from me.  i consider learning many things, either from julia or from python.  between that and certain disappointments with linux "pro audio," it's increasingly taking me away from desktop computing altogether.
Reply
#4
Put a string in the user defined type.
Store code in that string.
Write an interpreter that can run the code in that string. 
Make sure to check that code with your main program and have the results of any code it executes be responded to.
Tada ...you have methods.
Reply
#5
+1 I like that idea, if I were that desparate. Handling arguments might be tricky.
b = b + ...
Reply
#6
(01-25-2025, 04:36 PM)James D Jarvis Wrote: Put a string in the user defined type.
Store code in that string.
Write an interpreter that can run the code in that string. 
Make sure to check that code with your main program and have the results of any code it executes be responded to.
Tada ...you have methods.

this would work fabulously iff one is also "fluent" with julia, lua, python or other scripting language.  although it adds a layer of complication having to provide dynamic library and/or link with static library.

one thing i was supposed to be doing is to employ lua 5.4 as workhorse.  especially for math and for regular expressions.  take advantage also of the tables.  while i was forced to use only 32-bit linux.  i wrote a few functions in c that required linking with liblua.a, to come up with a "suffix-so" file.  one is a replication of _files$ in qb64 phoenix now.  another was a wave file loader, to do it much faster than by interpreted means.  i worked an awful lot with wave files using lua.  because i couldn't have qb64 or any other "real" programming system other than gcc.  i didn't have internet at that time and the computer i was using was failing.  this was until 2017 and the disaster that wasn't in texas.
Reply
#7
(01-22-2025, 05:38 AM)mcalkins Wrote: You're talking about classes? A class is a udt that can have member functions.

I know what classes are. I'm not thinking of them right now (inheritance and polymorphism are whole different cans of worms.) I can simulate the behavior I'm thinking of just by having a collection of SUBs that can be called with the type variable passed as an argument. But it would be handy sometimes to have the shorthand way to get the job done.
It's not the having, it's the doing.
Reply
#8
I like QB64 as is, because just like me, it has no class.

Pete Confused
Reply




Users browsing this thread: 7 Guest(s)