April 25, 2024, 10:05:52 AM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


OOP Tutorial 1

Started by Parker, March 07, 2007, 04:05:22 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Parker

This is the beginning of a mini-series of OOP tutorials with Emergence BASIC. Hopefully I can get some people into OOP programming by doing these. The first one will cover some basic concepts, and then more and more will be introduced with each tutorial. I will eventually cover inheritance, virtual functions and overriding, and information hiding, as well as other concepts.

This first tutorial covers the very basics of OOP. I will focus on what a class is used for and how it is different from a structure (TYPE). I will also explain class methods briefly.




In order to understand these tutorials, you should already be familiar with UDTs/structs (TYPEs). I will begin by pointing out the similarities between a class and a type.

For this tutorial, I will be extending the POINT type defined in EBSTD.INCC to the CPoint class. The point structure is defined like so:
TYPE POINT
DEF x as INT
DEF y as INT
ENDTYPE


Since the foundation of classes lies in types, we can simply change the word TYPE to CLASS, and we have a valid class. I am also going to change the name to CPoint so that it doesn't conflict with the type of the same name.
class CPoint
def x as int
def y as int
end class


That's our first class. You can use it in the same way as you would use a POINT. You can create variables of type CPoint, you can use NEW on it, and you can set and retrieve the member variables in the same way as you would a type. If that was all there was, there wouldn't be much of a point to make this into a class however.

One of the fundamental parts of classes are constructors and destructors. These are really just subroutines that are called by the compiler when you create or destroy a variable of a class type (I will call this a class instance from now on). The differences between constructors and destructors and regular subroutines is that for one they reside inside of the class, second they have a parameter called "THIS", and third they are called by the compiler when you create or destroy a class instance. For the purpose of this tutorial, we are going to pretend that we need a point for a coordinate system that starts at 1. This means that instead of 0 like EB sets variables to automatically, we should set x and y to 1 by default. We can use a constructor for this purpose. The destructor will remain empty for right now.

class CPoint
  def x as int
  def y as int
  declare CPoint( )
  declare _CPoint( )
end class

sub CPoint::CPoint( )
  x = 1
  y = 1
end sub

sub CPoint::_CPoint( )
end sub


Now if you create a CPoint instance, you will find that x and y are always initialized to 1. This is the magic of the compiler calling the constructor for us behind the scenes. We don't use our destructor for anything right now. Usually they are used to delete member variables (any variables stored inside of the class are called member variables), but another use is to let you know if you have a memory leak. If you put a PRINT statement in the constructor and the destructor, you should have one of each for every object that you create. If you are missing output from the destructor, you know it isn't being deleted somewhere.

You should be able to see how adding constructors and destructors worked. I simply put a declare statement inside of the class and then defined subroutines outside of it. These subroutines have a symbol that you may not have seen before. I used the :: to separate the class name and the method (subroutine) name. You can think of :: as 's. That is, if I had a statement
SUB TheClass::theSub()
you can think of this as defining TheClass's theSub. The subroutine theSub belongs to TheClass, or in this case CPoint() and _CPoint() belong to the CPoint class.

The other difference which I pointed out but didn't use in my code is the THIS pointer. THIS is not anything to worry about, it is just a pointer to the current instance of the class. When you write this code:
instance.method()
It is in effect the same as writing
CClass::method(instance)
where CClass is the type of 'instance'. However, we didn't give it a parameter. That is because the compiler automatically adds that parameter for us. It calls it "THIS", and it is always a pointer to what was before the '.'

If I were to rewrite my example to use the THIS pointer, it would look like this:
class CPoint
  def x as int
  def y as int
  declare CPoint( )
  declare _CPoint( )
end class

sub CPoint::CPoint( )
  *<CPoint>this.x = 1
  *<CPoint>this.y = 1
end sub

sub CPoint::_CPoint( )
end sub


At the current time EBASIC requires a typecast when dereferencing THIS, however this shouldn't be necessary in the future (hint hint ;))

At this time you may be wondering you need THIS when you don't have to use it (as I showed above). The reason is for when you have a parameter or a global variable with the same name as a member variable (or method). If you had a global variable named x, you would have to use THIS so that you didn't accidentally set the global x variable instead of the member x variable. However, there is no need in this example to use THIS. It doesn't make a difference either way. If you like it you can keep it in, otherwise you can remove it.

At this point we have a working, though simple class called CPoint that initializes its member variables x and y to 1, and contains a destructor. Next tutorial I will explain methods and add some to the class.

I will clarify any questions that you have. Just reply to this topic.

Parker

Dennisc

Hey, this is great! Thanks Parker.... :)
Failure is only the opportunity to begin again more intelligently
www.denniscomninos.com

Steve Rusich

Great OOP tutorial for us to use in Emergence BASIC! I am looking forward to reading the next one. 

Steve
Today I achieved unprecedented levels of unverifiable productivity.

Haim

Nice tutorial,
I liked it very much!
I find the idea of inserting a print statement in the destructor interesting for detecting possible memory leaks.
Is there a way to actually 'measure'  and quantify the amount of memory that might have leaked between construction and destruction of a class instance?

Haim

Parker

There is, and people have done it with C++, but it's complicated. It involves rewriting the new and delete functions to keep track of a block of memory and how much memory is allocated. I believe that there are also some programs that exist for this purpose, but in any case it's tricky and certainly beyond the scope of a tutorial like this.

I hope that answers your question.

Haim

hi,
Thanks for your response.
I wish there was something easy and simple  :)

Haim

Jerry Muelver

Parker, would it be all right to copy this tutorial (and following ones!) to the EBasic wiki?

Parker



Parker

I was going to add a link to this topic since it says to reply for questions at the bottom but I can't seem to find how to edit the wiki page. My username is virusscanner if I need to be approved. Thanks.

Jerry Muelver

You have to join Wikispaces first, then join the EBasic wiki. Look for the "join" buttons. Your login and password here on the forum is not connected with the wiki in any way.  ;)

Parker

Okay, I've requested membership. Thanks for adding the forum links too.

Jerry Muelver

Quote from: Parker on March 12, 2007, 08:09:28 PM
Okay, I've requested membership.
Yup. You're in!
QuoteThanks for adding the forum links too.
You're welcome. That's what wiki people do -- take care of each other.  ;)