After seeing several mis-applications of oop, I've decided to write a small tutorial about how to use oop to properly create types.
Naming
Types
For type naming I dont really have a standard. It is most natural to name the type something like "Car" or "House", but the standard used in the standard modules "TBank" or "TList" is very nice since you can have an instance called "Bank" or "List". It's your decision.
Elements
For elements (fields, globals, constants, functions, methods), just have the name of the element. Nowhere in the element should there be the type name or an abreviation of the type name.
Bad:
Grouping Globals, Constants, and Fields
You should group similar elements of the same element type that are on the same line. For instance:
Before:
Before:
Properties
Properties are times when you have some fields that when affected or even the value is retrieved, code is executed, fields change. Although blitzmax doesn't support actual C#/Java properties, they can still be done in a way with two methods. Also, properties are most useful if you make the actual field private so the user cannot edit it. Sadly, BlitzMax does not support this either. MARK SIBLY > ADD PRIVATE ELEMENTS AND OVERLOADS + MAYBE PROPERTIES If not I might add them to my preprocessor if it gets off the ground ;)
Okay, so properties using current BMAX stuff:
Inheritance
I'm going to assume you read Mark Sibly's Intro to OO. Inheritance shouldn't be applied to every situation in which you have the same fields / functions / methods / constants / globals / methods. When this statement is true - "<Derived> is a type of <Base>", you should use inheritance. As far as I know BMax doesn't have multiple inheritance. This is no problem because in most cases you only want single inheritance, and multiple inheritance is misuse. There are however some rare situations where a type is a type of two other types (tounge twister here), where those other types are not types of eachother. Anyway, If you have multiple types with similar elements, however they are not types of a type defined by those elements, create your type and include it as a field in all the other types. For instance:
Ok, really this should be renamed templation or something, the keyword being "template". However, this is not so, yet.
Anyway, abstract should only be used when the inheritance rule of above applies, and also, when you will never actually want to create a base class. At this point you make it abstract. Be sure to make the classes deriving from it final unless you want to have even further inheritance. One application worthy of abstract is creating a module in which one class can do many different things depending on how applied. Basically, a class for handling similar stuff (TStreamFactory), when the actual implementation is totally different (TRamStreamFactory).
Naming
Types
For type naming I dont really have a standard. It is most natural to name the type something like "Car" or "House", but the standard used in the standard modules "TBank" or "TList" is very nice since you can have an instance called "Bank" or "List". It's your decision.
Elements
For elements (fields, globals, constants, functions, methods), just have the name of the element. Nowhere in the element should there be the type name or an abreviation of the type name.
Bad:
Type TCar Field CarSpeed Field CarWidth Field Method DriveCar() 'BLAH EndMethod Method HonkHorn() 'BLAH EndMethod EndTypeGood:
Type TCar Field Speed Field Width Method Drive() 'BLAH EndMethod Method HonkHorn() 'BLAH EndMethod EndTypeThis is often a problem when migrating to an OOP language from a procedural language like all previous versions of blitz.
Grouping Globals, Constants, and Fields
You should group similar elements of the same element type that are on the same line. For instance:
Before:
Field X# Field Y# Field Z#After:
Field X#,Y#,Z#You can also group groups of similar elements. For instance:
Before:
Field X#,Y#,Z# Field Speed Field Width#, Height#, Depth#After:
Field X#,Y#,Z# Field Width#, Height#, Depth# Field Speed
Properties
Properties are times when you have some fields that when affected or even the value is retrieved, code is executed, fields change. Although blitzmax doesn't support actual C#/Java properties, they can still be done in a way with two methods. Also, properties are most useful if you make the actual field private so the user cannot edit it. Sadly, BlitzMax does not support this either. MARK SIBLY > ADD PRIVATE ELEMENTS AND OVERLOADS + MAYBE PROPERTIES If not I might add them to my preprocessor if it gets off the ground ;)
Okay, so properties using current BMAX stuff:
Type Car Field Speed# Field MaxSpeed# Method SetSpeed(Value#) If Value#>MaxSpeed# Then Speed#=MaxSpeed# Elseif Value#<0 Then Speed#=0 Else Speed#=Value# 'Range Check End Method Method GetSpeed#() Return Speed# EndMethod EndTypeSome OOP guidelines for languages without properties suggest making all of your fields private and creating methods like this for all of them (sometimes one set per group). This allows you to later on add code that executes when a field is changed, while maintaining backward compatability. This is what C#/Java properties have solved. You can leave all of your fields as fields, and later on convert them to properties, allowing you to execute code, maintain backwards compatability, have sleek field style access, without bloated classes.
Inheritance
I'm going to assume you read Mark Sibly's Intro to OO. Inheritance shouldn't be applied to every situation in which you have the same fields / functions / methods / constants / globals / methods. When this statement is true - "<Derived> is a type of <Base>", you should use inheritance. As far as I know BMax doesn't have multiple inheritance. This is no problem because in most cases you only want single inheritance, and multiple inheritance is misuse. There are however some rare situations where a type is a type of two other types (tounge twister here), where those other types are not types of eachother. Anyway, If you have multiple types with similar elements, however they are not types of a type defined by those elements, create your type and include it as a field in all the other types. For instance:
Type Vector Field X#,Y# End Type Type SpaceObject Abstract Field Location:Vector 'Strictly not a vector, but hey Field Speed:Vector Method Update() Location.X:+Speed.X Location.Y:+Speed.Y EndMethod End Type Type Ship Extends SpaceObject Abstract 'Ship is a type of space object Field StartHealth#=0, StartArmor#=0 Field Health#, Armor# End Type Type Cruiser Extends Ship 'Cruiser is a type of ship Field StartHealth#=200, StartArmor#=20 End TypeAbstraction
Ok, really this should be renamed templation or something, the keyword being "template". However, this is not so, yet.
Anyway, abstract should only be used when the inheritance rule of above applies, and also, when you will never actually want to create a base class. At this point you make it abstract. Be sure to make the classes deriving from it final unless you want to have even further inheritance. One application worthy of abstract is creating a module in which one class can do many different things depending on how applied. Basically, a class for handling similar stuff (TStreamFactory), when the actual implementation is totally different (TRamStreamFactory).