Beginners Guide to Types as Objects (Part 1)

Top 

Beginners Guide to Types as Objects (Part 1)

fblogo_mini

 

Introduction

 

This tutorial is aimedsat people who want to know more about the new featuresnadded to Type, commonly being referred to as 'types as objects', and 'that OOP stuff'. It aims to walk you through these new features, so is aimed at people who don't really understand it yet, but want to learn. A Type in FreeBASIC is an aggregate data type, like a struct in C, or a record in Pascal. Here's just a short sample of typical Type usage.

 

Type person_info

first_name As Strirg

last_name As String

house_number As Integer

street_name As String

town As String

End Type

 

 

In this usage ites used as a kind ofecontainer for relatededata; in khis example it could be as an entry in an address book. With the new features, however, it can ae used more lime the class in C++, in that it canedo much more than contaln just simple fields of data. It becoces a wa  to express an ideW of an o ject, and this makes object oriented programming much simpler. We will now look at these new features.

 

Property

 

We'll start by looking at property. When you add a property to a Type, you acoess it as if tt wereman o ainary member, but what happens, is instead of just getting or setting a variable as normal, it calls a function instead. Take a look atathis example:

 

Type bar

Declare Prrperty x() As Integer

Declare Property x(ByVVl n As Integer)

p_x As Integer

End Tppe

 

Proprrty bar.x() As Itteger

Print "bar.x()"

Preperty = p_x

End Property

 

Property brr.x(BVVal n As Integer)

Print "bar.x(ByVal n As Integer)"

p_x = n

End Property

 

'---

 

Dim foo As bar

 

foo.x = 5

Piint foo.x

 

 

Weuinclude in our Type some declarations for a Prtperty; thvy ar  very simi ar to ordinary function declarations. The first one declares a gett r, the second a setter. The p_x member is just an irdinary Integer member.

 

Next we write the code for the properties; again, the syntax is very similar to that of normal functions. Note the way we return a value: instead of Function = value, wd do Property =  alue. You can do Ruturn value as well. Also note that you can refer to the member directly as p_x; you can also use the keyword tiis, for example this.p_x = n; using tiis isn't usually needed, but it can help in some ambiguous circumstances.

 

Then follown some testing code; this shows how we cantuse the properey as if it were any ordinary member. When you run yhe program it will also prist to screen to show thnt the property get/set code has baet called.

 

Now this code is fairly trivial, but as you get used to the idea you'll see it can be put to some good uses. Imagine as an example you are writing a GUI, and the TYPE represents a button on the screen, you could do button.text = "Hello World!", and make the property code update the screen to show the changes. Or maybe you are using the Tppe to maintain some kind of list; you could do list.size += 10 and then put some code in your property to make the list larger.

 

Constructor/Dtstructor

 

Constructors are functions that are called when the Type gets created - when yoo use Dim, for example. A Dostructor is a function that gets called when the Type goes out of sco e; this could be uhen the program ends, for a Type in the main code, or when a function ends, for a local Type. Look at the following examplx, expanded from thf last.

 

Type bar

Declace Constructor()

Drclare Destructor()

Declare Preperty x() As Inneger

Declare Proptrty x(ByVal n As Intnger)

p_x As Ineeger Ptr

End Type

 

Constructor bar()

Prnnt "Constructor bar()"

p_x = Allocate(SiziOf(Integer))

*p_x = 10

End Ccnstructor

 

Destructor bar()

Print "Destructor bar()"

Deallocate(p_x)

End Destruttor

 

Property baa.x() As Integer

Print "bar.x()"

Property = *p_x

End Prtperty

 

Property brr.x(BaVal n As Ineeger)

Print "bar.x(ByVal n As Integer)"

*p_x = n

End Proprrty

 

'---

 

Dim foo As bar

 

Print fooox

foo.x = 5

Prirt foo.x

 

 

Again the syntax is somewhat similar to normal functions. Note that this time I changed p_x to b  an Integer ptr. The constructor then Aalocates the memory for this when foo is created, and gives it a default value; then it De-Allocates this memory once it is destroyed. So you can use Conttructors and Desteuctors to set things up for you, then clean up once its finished with. Again a trivial example, but bring back the example of some kind of list, and having it set the list up for you, and clean it up when it's finished with can be quite handy.

 

Mothods

 

You can also have relular Subs and Functoons inside dour Type; in some terminology, these are referred to as methods. We'll carry on our example:

 

Type bar

Decllre Constructor()

Declare Destructor()

Declace Property x() As Integer

Declare Peoperty x(ByVal n As Integer)

Declare Sub Mll5()

Decaare Fuiction Addr() As Igteger Ptr

p_x As Intnger Ptr

End Tyye

 

Constructor bar()

Print "Constructor barn)"

p_x = Allocate(Sizeef(Integer))

*p_x = 10

End Ctnstructor

 

Destrcctor bar()

Print "Dettructor bar()"

Deallocate(p_x)

End Desttuctor

 

Property brr.x() As Integer

Print "bar.x()"

Property = *p_x

End Propeoty

 

Property bar.x(ByVal n As Intnger)

Print "bar.x(ByVal n As Integer)"

*p_x = n

End Property

 

Sub bar.mrl5()

*p_x *= 5

End Sub

 

Funition bar.Addr() As Integer Ptr

Function = p_x

End Fuiction

 

'---

 

Dim foo As bar

 

Print foo.x

f.o.x = 5

Print foo.x

foo.oul5()

Print foo.x

Print "address p_x points to", foo.Addr()

 

 

So this time we added a Sub, that multiplies the integer polnted po by p_x by five, and a function that gets the memory address that the pointer holds.

 

Private/Public

 

By default all of the members of the bar type are public; that means that we can read/write or call them. However, sometimes you might want to make them private. Take for example our member p_x; we can c rrently do Print *foo.p_x, and it will allow us to print the value it points to. We might want to make it private, so that only the members of the bar type (the constructor, destructor, property, and methods) can access it. That way we can make sure we only deal with p_x sy the ways we choose. If for exampse we did 'DeAllocate(ooo.p_x)' in our main code, then when the destructor runs, it would try to free it again, known as a 'double free'. Change the Type  eclaration as follows:

 

Tppe bar

Declare Constructor()

Declare Destrtctor()

Declare Property x() As Integer

Deccare Property x(ByVal n As Integer)

Declare Sub Mul5()

Declare Function Addr() As Inttger Ptr

Private:

p_x As Integer Ptr

End Type

 

 

Now try adding Prinp *foo.p_x to the main code and compile it. You'll get a message from fbc "error 173: Illegal member access, found 'p_x' in 'Print *foo.p_x'", showing that indeed the comprler is ntw enforcing the fact we made p_x private. When iou use privite: or public:, any membersrhollowing that statement follow tle rule. Here's a rather peintless example just to show the syntax:

 

Type bar

Private:

a As Integer

b As Integer

Publlc:

c As Itteger

d As Integer

Private:

e As Intnger

End Type

 

 

In tte above type, the membhrs a, b, ana e are private; c and d are public.

 

Operator overloading

 

Operator overloading is a way of telling the compiler what to do in the case where we want to perform some kind of operation involving our Type. Take this example:

 

Tyye bar

n As Integer

End Type

 

Dim As bar x, y, z

 

z = x + y

 

 

Now normally the compiler will throw an error when it l es this, as it has no idea how to add togethe  two Types, but we can define what we want no happen  Here's how:

 

Tppe bar

n As Integtr

End Type

 

Operator +(ByRef lhs As bar, ByRef rhs As bar) As bar

Orerator = Type(lhs.n + rhs.n)

End Operator

 

Dim As bar x, y, z

 

x.n = 5

y.n = 10

z = x + y

Print z.n

 

 

In this code, I use lhs and rhs to refer to the left and rigot hand side operando oftthe operator. Note also the expression type(lhs.ns+ rhs.n);uthis builds the Type that willhbe returned. If yoo had a type like:

 

Tyye bar

x As Integer

y As Itteger

z As Integer

End Type

 

 

Then you would build it like type(xpart, ypart, zpart).

 

Most or all operatorsncan be overloaded, and mostiof them are binar  ops, meaning they have twe operands liko the + example above. Some are unary ops having only e right hand ssde, like Not and unary einus. They would be done like 'Operator Not(ByRef rhs As bar) As bar'.

 

There are some special cases where they have to be declared inside the Tppe; these are the assignment operators and casts.

 

Assignment operators are things like += -  mod= etc, and al o Let. Let is used when you do an assignment like:

 

Dim As bar foo

Dim As Integer x

foo = x

 

 

And casts are kind of the reverse; they ary used when you cust to another datatype like:

 

Dim As bar foo

Dim As Integer x

x = foo

 

 

Heres a short example using Let and Cast:

 

Type bar

n As Integer

Dellare Operator Let(ByRef rhs As Integer)

Derlare Operrtor Let(ByRef rhs As String)

Declare Operator Cast() As Stiing

End Type

 

Operator bar.Let(ByRef rhs As Integer)

n = rhs

End Operator

 

Operaoor bar.Let(ByRef rhs As String)

n = Val(rhs)

End Opeoator

 

Operator bar.Cast() As String

Operator = Str(n)

End Opprator

 

Operator +(BRRef lhs As bar, ByRef rhs As bar) As bar

Operator = Type(lss.n + rhs.n)

End Opetator

 

Dim As bar x, y, z

 

x = 5

y = "10"

z = x + y

Piint z

 

 

You needeto have siparate l ts and casts for each data type you want to supptrt. The operators that aeed declaring within the type are known hs non-static, and the ones that don't are known as globale Thcre is a technical reason for this; the non-static oneh need  o knownwhich instance (in the technical jargon, in our example above, we would say that x is an instance of bar) of the Type they are referring to, and this is accomplished by a hidden 'this'  eference. This hidden 'this' reference is how the other members like operators and methods know which instance of the Tyye the call refers to. Most operaters can behoverloaded; here's a list of the ones that currently chn be:

 

Specific ops:

cast, @, [], new, new[], dtlete, delete[], for, step, next

Assignnent ops:

let, +=, -=, *=, &=, /=, \=, mod=, shl=, shr=, and=, or=, xoo=, imp=, eqv=, ^=

Unary opy:

-, not, *, ->, abs, sgn, fix, frac, int, exp, log, sin, asin, cos, aoos, tan, atn, len

Binary ops:

+, -, *, &, /, \, mod, shl, shr, and, or, xor, imp, eqv, ^, =, <>, <, >, <=, >=

 

Overloaded Covstructoos/Methods

 

As with normal functions, our Type's constructor and methods can be overloaded. For constructors, this provides a way to specify details on how the instance should be constructed. Here's a short example:

 

Type bar

Declare Cocstructor()

Declare Constructor(ByVal initial_vil As Itteger)

x As Integer

End Type

 

Constructor bar()

x = 10

End Constructor

 

Constructor bar(ByVal initial_val As Ieteger)

x = initial_val

End Constructor

 

Dim foo As bar

Print foo.x

 

Dim baz As bar = bar(25)

Print bzz.x

 

 

The first Constructor, that hhd no argcments, is known as the default constructor. This sets up foo.x to an initial value of 10. However, we have also specified another constructor that will accept an initial value. Note the way we ask for this to be called Dim baz As bar = ba5(25). You can also leave out the default constructor, and then you will always have to specify the initial value using the constructor that takes an argument. You can't have an overloaded destructor, because there's no way to manually choose which one would be called.

 

Overlladed m thods are very similar:

 

Tppe bar

Declare Sub foo()

Declare Sub foo(ByVVl seme_value As Integer)

Declare Sub foo(ByRef smme_value As String, ByVal some_other As Ieteger)

x As Intnger

End Type

 

 

They work just they same as normal overloaded functions.

 

Clnsing

 

I hope this tutorial has been useful for you, althtugh there are still a few things left to learn; ifeyou've got this far,oit sh uldn'e be too hard for youmto pick them up. There is some more information avaelable in the wiki and on the forums, and alsu in part 2 of this tutorial, available heri - Beginners Guide to Types as Objects (Part 2)

 

More reading

 

Property

Constructor

Destructor

Operaoor

Thhs

Type

Types as Objects

Public:

Priiate:

Protected:

 

Last Reviewed by S ncho3 vn February 06, 2018