Here's something I knocked up a while back and plan to 'extend' (hur, hur) one day:
Crash course in OO programming for Blitz coders
Welcome to a crash course in OO programming for Blitz coders!
OO stands for 'Object Oriented'. OO is a programming paradigm or 'way of thinking' that has taken on almost mythical proportions over the years yet, somewhat unusually for the world of computing, is actually quite useful!
*Disclaimer* - OO coding means different things to different people. This article is strongly swayed by my own experience with OO coding and what I like and find useful about it. The actual 'meaning' of OO is almost as fun to argue about as whether the universe is infinite or not.
First up, OO coding has spawned a bunch of initially confusing but actually quite sensible buzzwords, including such gems as:
Inheritance,
Multiple Inheritance,
Polymorphism,
Virtual,
Abstract,
Concrete,
Type,
Class,
Object,
Instance,
Base Class,
Derived Class,
Super Class,
Sub Class,
Scary stuff!
Well, not really. Never forget that behind the scenes its all just a bunch of bits and bytes and Ifs and Adds and Gotos.
As always, its easier than the guys who get paid megabucks to do it would have us think.
Part 1 : Inheritance.
--------------------------
Inheritance is a way of 'composing' objects from other objects.
This is already possible in procedural Blitz. Consider the following code...
Type Part1
Field x,y,z
End Type
Type Part2
Field p1.Part1
Field p,q,r
End Type
Function UpdatePart1( t:Part1 )
'Do something clever with a Part1.
End Function
This is one way of composing objects. Part2 'contains' a Part1, via the p1 field.
If you've got a Part2 object and want to call UpdatePart1(), you can grab the p1 field and use it in the function call, for example:
Local t:Part2=New Part2
t.p1=New Part1 'need to create it!
UpdatePart1 t.p1
OO inheritance provides a different (not always better!) way to do this:
Type Base
Field x,y,z
End Type
Type Derived Extends Base
Field p,q,r
End Type
Function UpdateBase( t:Base )
'Do something clever with a Base object.
End Function
Ok, we've already hit our first OO buzzwords - Base and Derived. These are not special keywords, they are just names I chose for these types. Bear with me and hopefully you'll get some idea of why I chose them.
First up, The Base type is just the same as the procedural Part1 type - no problem there.
The Derived type, however, introduces us to the Extends keyword, which is used to indicate inheritance.
Extends always appears after 'Type whatever', and means that the type you are describing extends a different, existing type. So the type you are describing is composed not only of the fields and stuff you declare, but also the fields and stuff of the type you are extending!
This means that the Derived type above actually has the additional fields x,y,z - these have been 'inherited' from the Base type. It is then perfectly legal for you to code up something like:
Local t:Derived=New Derived
t.x=100 'x inherited from Base - thanks Base, you rock!
Another way to think of it is the Derived type 'is a' Base type, but with some extra stuff. In fact, in OO terminology 'IsA' is often used to indicate inheritance or inheritance-like properties.
Now it gets a bit interesting. Since our Derived type 'is a' Base type, its perfectly legal to use it where ever a Base type is expected - for example, the UpdateBase() function:
Local MyDerived:Derived=New Derived 'fine...
UpdateBase MyDerived 'What?!?
Initially, this looks *wrong* - 'Type mismatch error' looms! But in OO code its fine. Since Derived Extends Base, its OK to use a Derived where ever a Base is expected - even in assignments:
Local MyBase:Base=New Derived 'Okay, because Derived Extends (or 'Is a') Base.
In addition, there could be many types extending Base, and each of these could be used interchangeably with Base.
Hopefully the terms 'Base' and 'Derived' now mean something. The Derived type is derived from, or 'comes from', the Base type.
Remember that Base and Derived are just names I chose for this example. In real world coding, you'd use useful names, for example:
Type Actor
Field x,y,z
End Type
Type Player Extends Actor
Field lives,score
End Type
But still, you can think of Actor as the base type, and Player as the derived type - a Player is derived from an Actor.
Its also perfectly legal (and very useful!) to extend extended types, for example:
Type Actor
Field x,y,z
End Type
Type Player Extends Actor
Field lives,score
End Type
Type Enemy Extends Actor
Field mood
End Type
Type Troll Extends Enemy
Field grudge_quotient
End Type
Type Ghoul Extends Enemy
Field lust_for_life
End Type
So, if you've got a function like UpdateActor( t:Actor ), you can pass it any of the above types as they are all ultimately derived from Actor.
Similarly, a RethinkMood( t:Enemy ) function could be used with any of the bad guys (Enemy, Troll or Ghoul) - but not with players, as Player is not derived from Enemy.
This is what is known as a 'class hierarchy' - a 'tree' of types.
Crash course in OO programming for Blitz coders
Welcome to a crash course in OO programming for Blitz coders!
OO stands for 'Object Oriented'. OO is a programming paradigm or 'way of thinking' that has taken on almost mythical proportions over the years yet, somewhat unusually for the world of computing, is actually quite useful!
*Disclaimer* - OO coding means different things to different people. This article is strongly swayed by my own experience with OO coding and what I like and find useful about it. The actual 'meaning' of OO is almost as fun to argue about as whether the universe is infinite or not.
First up, OO coding has spawned a bunch of initially confusing but actually quite sensible buzzwords, including such gems as:
Inheritance,
Multiple Inheritance,
Polymorphism,
Virtual,
Abstract,
Concrete,
Type,
Class,
Object,
Instance,
Base Class,
Derived Class,
Super Class,
Sub Class,
Scary stuff!
Well, not really. Never forget that behind the scenes its all just a bunch of bits and bytes and Ifs and Adds and Gotos.
As always, its easier than the guys who get paid megabucks to do it would have us think.
Part 1 : Inheritance.
--------------------------
Inheritance is a way of 'composing' objects from other objects.
This is already possible in procedural Blitz. Consider the following code...
Type Part1
Field x,y,z
End Type
Type Part2
Field p1.Part1
Field p,q,r
End Type
Function UpdatePart1( t:Part1 )
'Do something clever with a Part1.
End Function
This is one way of composing objects. Part2 'contains' a Part1, via the p1 field.
If you've got a Part2 object and want to call UpdatePart1(), you can grab the p1 field and use it in the function call, for example:
Local t:Part2=New Part2
t.p1=New Part1 'need to create it!
UpdatePart1 t.p1
OO inheritance provides a different (not always better!) way to do this:
Type Base
Field x,y,z
End Type
Type Derived Extends Base
Field p,q,r
End Type
Function UpdateBase( t:Base )
'Do something clever with a Base object.
End Function
Ok, we've already hit our first OO buzzwords - Base and Derived. These are not special keywords, they are just names I chose for these types. Bear with me and hopefully you'll get some idea of why I chose them.
First up, The Base type is just the same as the procedural Part1 type - no problem there.
The Derived type, however, introduces us to the Extends keyword, which is used to indicate inheritance.
Extends always appears after 'Type whatever', and means that the type you are describing extends a different, existing type. So the type you are describing is composed not only of the fields and stuff you declare, but also the fields and stuff of the type you are extending!
This means that the Derived type above actually has the additional fields x,y,z - these have been 'inherited' from the Base type. It is then perfectly legal for you to code up something like:
Local t:Derived=New Derived
t.x=100 'x inherited from Base - thanks Base, you rock!
Another way to think of it is the Derived type 'is a' Base type, but with some extra stuff. In fact, in OO terminology 'IsA' is often used to indicate inheritance or inheritance-like properties.
Now it gets a bit interesting. Since our Derived type 'is a' Base type, its perfectly legal to use it where ever a Base type is expected - for example, the UpdateBase() function:
Local MyDerived:Derived=New Derived 'fine...
UpdateBase MyDerived 'What?!?
Initially, this looks *wrong* - 'Type mismatch error' looms! But in OO code its fine. Since Derived Extends Base, its OK to use a Derived where ever a Base is expected - even in assignments:
Local MyBase:Base=New Derived 'Okay, because Derived Extends (or 'Is a') Base.
In addition, there could be many types extending Base, and each of these could be used interchangeably with Base.
Hopefully the terms 'Base' and 'Derived' now mean something. The Derived type is derived from, or 'comes from', the Base type.
Remember that Base and Derived are just names I chose for this example. In real world coding, you'd use useful names, for example:
Type Actor
Field x,y,z
End Type
Type Player Extends Actor
Field lives,score
End Type
But still, you can think of Actor as the base type, and Player as the derived type - a Player is derived from an Actor.
Its also perfectly legal (and very useful!) to extend extended types, for example:
Type Actor
Field x,y,z
End Type
Type Player Extends Actor
Field lives,score
End Type
Type Enemy Extends Actor
Field mood
End Type
Type Troll Extends Enemy
Field grudge_quotient
End Type
Type Ghoul Extends Enemy
Field lust_for_life
End Type
So, if you've got a function like UpdateActor( t:Actor ), you can pass it any of the above types as they are all ultimately derived from Actor.
Similarly, a RethinkMood( t:Enemy ) function could be used with any of the bad guys (Enemy, Troll or Ghoul) - but not with players, as Player is not derived from Enemy.
This is what is known as a 'class hierarchy' - a 'tree' of types.