User Tools

Site Tools


object_20oriented_20programming_20_28lbb_29

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

object_20oriented_20programming_20_28lbb_29 [2018/03/31 13:19]
127.0.0.1 external edit
object_20oriented_20programming_20_28lbb_29 [2018/04/17 18:01] (current)
tbest3112 Added syntax highlighting
Line 4: Line 4:
 ===== Classes and Objects ===== ===== Classes and Objects =====
 \\  Object Oriented Programming has the concept of a **class**. A class is just a bundled collection of data along with the code which operates on it (the data are often referred to as the **properties** of the class and the code, consisting of subroutines and functions, as the **methods** of the class). Not only does the class bundle the related items together, it (typically) isolates the data from being accessed from outside the class - rather as variables (other than GLOBALS) referenced inside a function or subroutine are inaccessible from outside.\\ \\  Hopefully you can see how this is helpful. It is obvious at a glance what data is related to what code, and the '​methods'​ can only operate on the '​properties'​ in the same class (see later for how classes can be combined). This makes the code more understandable and more reliable, and allows modifications to be made with more confidence.\\ \\  But this is all rather theoretical,​ and it may be easier to understand by way of example. Imagine that in a program we want to represent a **vehicle**;​ all vehicles have certain properties in common, these might be things like the speed with which it is moving. We also want to be able to perform certain operations on that vehicle, such as increase its speed (accelerate) or decrease its speed (decelerate).\\ \\  In Object Oriented Liberty BASIC (OOLB) we can define a class to represent a vehicle as follows:​\\ ​ \\  Object Oriented Programming has the concept of a **class**. A class is just a bundled collection of data along with the code which operates on it (the data are often referred to as the **properties** of the class and the code, consisting of subroutines and functions, as the **methods** of the class). Not only does the class bundle the related items together, it (typically) isolates the data from being accessed from outside the class - rather as variables (other than GLOBALS) referenced inside a function or subroutine are inaccessible from outside.\\ \\  Hopefully you can see how this is helpful. It is obvious at a glance what data is related to what code, and the '​methods'​ can only operate on the '​properties'​ in the same class (see later for how classes can be combined). This makes the code more understandable and more reliable, and allows modifications to be made with more confidence.\\ \\  But this is all rather theoretical,​ and it may be easier to understand by way of example. Imagine that in a program we want to represent a **vehicle**;​ all vehicles have certain properties in common, these might be things like the speed with which it is moving. We also want to be able to perform certain operations on that vehicle, such as increase its speed (accelerate) or decrease its speed (decelerate).\\ \\  In Object Oriented Liberty BASIC (OOLB) we can define a class to represent a vehicle as follows:​\\ ​
 +<code lb>
       CLASS Vehicle       CLASS Vehicle
         DIM speed         DIM speed
Line 19: Line 20:
         END FUNCTION         END FUNCTION
       END CLASS       END CLASS
 +</​code>​
 \\  The **properties** of the class are listed in one or more DIM statements; they may include numbers, strings and arrays (we will see later that it's also possible to include '​child'​ classes). The **methods** of the class provide the means to manipulate those properties, and a means to discover the value of a property (if it needs to be known outside the class).\\ \\  So we have a simple class which represents a vehicle. But in the program there may be several different vehicles, with different speeds and other properties. This is where the real power of Objects comes in. The '​class'​ is like a template: it describes a vehicle **in general**. An '​object'​ is a specific case of that class (it's usually called an **instance** of the class) and describes a particular vehicle.\\ \\  In OOLB we create an object (an instance of a class) as follows:​\\ ​ \\  The **properties** of the class are listed in one or more DIM statements; they may include numbers, strings and arrays (we will see later that it's also possible to include '​child'​ classes). The **methods** of the class provide the means to manipulate those properties, and a means to discover the value of a property (if it needs to be known outside the class).\\ \\  So we have a simple class which represents a vehicle. But in the program there may be several different vehicles, with different speeds and other properties. This is where the real power of Objects comes in. The '​class'​ is like a template: it describes a vehicle **in general**. An '​object'​ is a specific case of that class (it's usually called an **instance** of the class) and describes a particular vehicle.\\ \\  In OOLB we create an object (an instance of a class) as follows:​\\ ​
 +<code lb>
       NEW MyVehicle1 AS Vehicle       NEW MyVehicle1 AS Vehicle
 +</​code>​
 \\  The object **MyVehicle1** has a speed (and other properties, if any) independent of any other objects in the program. Let's put all this together into our first complete Object Oriented Liberty BASIC program:​\\ ​ \\  The object **MyVehicle1** has a speed (and other properties, if any) independent of any other objects in the program. Let's put all this together into our first complete Object Oriented Liberty BASIC program:​\\ ​
 +<code lb>
       NEW MyVehicle1 AS Vehicle       NEW MyVehicle1 AS Vehicle
  
Line 49: Line 54:
         END FUNCTION         END FUNCTION
       END CLASS       END CLASS
 +</​code>​
 Here we have introduced a couple of things you haven'​t seen before. Firstly, to call a method (subroutine or function) in an object we use the familiar LB syntax but the name consists of the name of the object followed by two colons (this is called the //scope resolution operator//) and then the name of the method within that object, i.e. **Object::​Method**.\\ \\  Secondly, when we have finished with an object we **DISCARD** it. This frees the memory resources which were allocated to the object with **NEW**.\\ \\  Here we have introduced a couple of things you haven'​t seen before. Firstly, to call a method (subroutine or function) in an object we use the familiar LB syntax but the name consists of the name of the object followed by two colons (this is called the //scope resolution operator//) and then the name of the method within that object, i.e. **Object::​Method**.\\ \\  Secondly, when we have finished with an object we **DISCARD** it. This frees the memory resources which were allocated to the object with **NEW**.\\ \\ 
 ===== Private methods ===== ===== Private methods =====
 \\  Some methods may be intended to be called only from other methods within the same class, rather than from outside the class. It is possible to specify such methods as **PRIVATE** in which case an attempt to call them from outside the class will fail at run-time. Here is an example:​\\ ​ \\  Some methods may be intended to be called only from other methods within the same class, rather than from outside the class. It is possible to specify such methods as **PRIVATE** in which case an attempt to call them from outside the class will fail at run-time. Here is an example:​\\ ​
 +<code lb>
       NEW MyVehicle1 AS Vehicle       NEW MyVehicle1 AS Vehicle
  
Line 83: Line 90:
         END FUNCTION         END FUNCTION
       END CLASS       END CLASS
 +</​code>​
 Here, instead of the **accelerate** and **decelerate** methods altering the speed value directly, they each call a PRIVATE method **adjust** which does so. Note the syntax for calling a method in the same class: specify the object name as **this**.\\ \\  Here, instead of the **accelerate** and **decelerate** methods altering the speed value directly, they each call a PRIVATE method **adjust** which does so. Note the syntax for calling a method in the same class: specify the object name as **this**.\\ \\ 
 ===== Constructors and Destructors ===== ===== Constructors and Destructors =====
 \\  You will notice that in the class **Vehicle** the value of **speed** is not initialised. Just as with ordinary LB variables and arrays, the value is assumed to be zero or an empty string if not previously set. Of course we could have provided an explicit method for initialising the speed, but there is another approach.\\ \\  It is possible to incorporate a special method called the **constructor**. The constructor takes the form of an ordinary subroutine but instead of being deliberately executed using CALL it is //​automatically//​ called when the object is created. The constructor is distinguished by having a name which is the same as the name of the class. Let's modify our program accordingly:​\\ ​ \\  You will notice that in the class **Vehicle** the value of **speed** is not initialised. Just as with ordinary LB variables and arrays, the value is assumed to be zero or an empty string if not previously set. Of course we could have provided an explicit method for initialising the speed, but there is another approach.\\ \\  It is possible to incorporate a special method called the **constructor**. The constructor takes the form of an ordinary subroutine but instead of being deliberately executed using CALL it is //​automatically//​ called when the object is created. The constructor is distinguished by having a name which is the same as the name of the class. Let's modify our program accordingly:​\\ ​
 +<code lb>
       NEW MyVehicle1 AS Vehicle       NEW MyVehicle1 AS Vehicle
  
Line 121: Line 130:
         END FUNCTION         END FUNCTION
       END CLASS       END CLASS
 +</​code>​
 Here the speed is automatically initialised to 2 when the object is created.\\ \\  Suppose we want to be able to initialise the speed to a different value for each instance of the class. Again we could do that by calling a method, but it's also possible to pass one or more parameters to the constructor:​\\ ​ Here the speed is automatically initialised to 2 when the object is created.\\ \\  Suppose we want to be able to initialise the speed to a different value for each instance of the class. Again we could do that by calling a method, but it's also possible to pass one or more parameters to the constructor:​\\ ​
 +<code lb>
       NEW MyVehicle1 AS Vehicle 3 ' parameter passed to constructor       NEW MyVehicle1 AS Vehicle 3 ' parameter passed to constructor
  
Line 157: Line 168:
         END FUNCTION         END FUNCTION
       END CLASS       END CLASS
 +</​code>​
 \\  You probably won't be surprised to learn that as well as a constructor,​ which is called automatically when an object is created, we can also have a **destructor** which is called automatically when the object is discarded. A destructor has a name consisting of a tilde (~) followed by the name of the class; in this case there is nothing useful for it to do so we will just print a message:​\\ ​ \\  You probably won't be surprised to learn that as well as a constructor,​ which is called automatically when an object is created, we can also have a **destructor** which is called automatically when the object is discarded. A destructor has a name consisting of a tilde (~) followed by the name of the class; in this case there is nothing useful for it to do so we will just print a message:​\\ ​
 +<code lb>
       NEW MyVehicle1 AS Vehicle 3 ' parameter passed to constructor       NEW MyVehicle1 AS Vehicle 3 ' parameter passed to constructor
  
Line 197: Line 210:
         END FUNCTION         END FUNCTION
       END CLASS       END CLASS
 +</​code>​
 \\  \\ 
 ===== Inheritance ===== ===== Inheritance =====
 \\  We have seen how to create a class which represents a vehicle, but there are different kinds of vehicles (cars, bicycles etc.). Suppose we want to create a class to represent a **bicycle**;​ we could start from scratch and define the properties and methods that a bicycle needs. But a better way is to recognise that a bicycle is a kind of vehicle, so any property or method relevant to a vehicle should also be relevant to a bicycle - although a bicycle may have properties and methods of its own.\\ \\  We can do that using a variation of the CLASS statement as follows:​\\ ​ \\  We have seen how to create a class which represents a vehicle, but there are different kinds of vehicles (cars, bicycles etc.). Suppose we want to create a class to represent a **bicycle**;​ we could start from scratch and define the properties and methods that a bicycle needs. But a better way is to recognise that a bicycle is a kind of vehicle, so any property or method relevant to a vehicle should also be relevant to a bicycle - although a bicycle may have properties and methods of its own.\\ \\  We can do that using a variation of the CLASS statement as follows:​\\ ​
 +<code lb>
       CLASS Bicycle INHERITS Vehicle       CLASS Bicycle INHERITS Vehicle
 +</​code>​
 The INHERITS keyword specifies that the class **Bicycle** inherits all the properties and methods of the class **Vehicle**. You can then specify additional properties and additional methods which are needed by a bicycle but not by vehicles in general. Here I have chosen the current gear and the gear ratios:​\\ ​ The INHERITS keyword specifies that the class **Bicycle** inherits all the properties and methods of the class **Vehicle**. You can then specify additional properties and additional methods which are needed by a bicycle but not by vehicles in general. Here I have chosen the current gear and the gear ratios:​\\ ​
 +<code lb>
       NEW MyBicycle1 AS Bicycle 2,3,5,7,10 ' parameters passed to constructor       NEW MyBicycle1 AS Bicycle 2,3,5,7,10 ' parameters passed to constructor
  
Line 265: Line 282:
         END FUNCTION         END FUNCTION
       END CLASS       END CLASS
 +</​code>​
 The order of declaration is important: ancestor classes must be declared before their descendant classes.\\ \\  The order of declaration is important: ancestor classes must be declared before their descendant classes.\\ \\ 
 ===== Overriding methods ===== ===== Overriding methods =====
 \\  As we have seen, when a class INHERITS another class it acquires the properties and methods of its ancestor class. However it is still possible to declare a method in the descendant class which has the same name as one in the ancestor class. In that case the declaration in the descendant class takes precedence. For example:​\\ ​ \\  As we have seen, when a class INHERITS another class it acquires the properties and methods of its ancestor class. However it is still possible to declare a method in the descendant class which has the same name as one in the ancestor class. In that case the declaration in the descendant class takes precedence. For example:​\\ ​
 +<code lb>
       NEW MyBicycle1 AS Bicycle 2,3,5,7,10 ' parameters passed to constructor       NEW MyBicycle1 AS Bicycle 2,3,5,7,10 ' parameters passed to constructor
  
Line 335: Line 354:
         END FUNCTION         END FUNCTION
       END CLASS       END CLASS
 +</​code>​
 Here I have re-defined the **accelerate** method so that it takes account of the gear ratio.\\ \\  Here I have re-defined the **accelerate** method so that it takes account of the gear ratio.\\ \\ 
 ===== Containment ===== ===== Containment =====
 \\  As described in the previous section, inheritance represents an 'is a' relationship:​ a bicycle **is a** vehicle. A related concept is that of containment,​ which represents the 'has a' relationship. For example a bicycle **has** wheels. A class can only //inherit// from one ancestor class, but it can //contain// several child classes.\\ \\  Here is an example. We will first declare a new class **Wheel** which has a property **diameter**,​ a method to set its value, and a method to get its value:​\\ ​ \\  As described in the previous section, inheritance represents an 'is a' relationship:​ a bicycle **is a** vehicle. A related concept is that of containment,​ which represents the 'has a' relationship. For example a bicycle **has** wheels. A class can only //inherit// from one ancestor class, but it can //contain// several child classes.\\ \\  Here is an example. We will first declare a new class **Wheel** which has a property **diameter**,​ a method to set its value, and a method to get its value:​\\ ​
 +<code lb>
       CLASS Wheel       CLASS Wheel
         DIM diameter         DIM diameter
Line 349: Line 370:
         END FUNCTION         END FUNCTION
       END CLASS       END CLASS
 +</​code>​
 Note that a method which sets the value of a property is sometimes called a **setter** and a method which gets the value of a property a **getter**; together they are known as **accessors**.\\ \\  We can now add some wheels to our class **Bicycle**:​\\ ​ Note that a method which sets the value of a property is sometimes called a **setter** and a method which gets the value of a property a **getter**; together they are known as **accessors**.\\ \\  We can now add some wheels to our class **Bicycle**:​\\ ​
 +<code lb>
       NEW MyBicycle1 AS Bicycle 2,3,5,7,10 ' parameters passed to constructor       NEW MyBicycle1 AS Bicycle 2,3,5,7,10 ' parameters passed to constructor
  
Line 438: Line 461:
         END FUNCTION         END FUNCTION
       END CLASS       END CLASS
 +</​code>​
 Note that to call a method in a contained class the //scope resolution operator// is once again used, i.e. **Child::​Method**.\\ \\  Note that to call a method in a contained class the //scope resolution operator// is once again used, i.e. **Child::​Method**.\\ \\ 
 ===== Arrays of objects ===== ===== Arrays of objects =====
 \\  Up to now we have //​instantiated//​ objects individually,​ but it is possible to instantiate an **array** of objects. For example if we have five bicycles we can use an array for them:​\\ ​ \\  Up to now we have //​instantiated//​ objects individually,​ but it is possible to instantiate an **array** of objects. For example if we have five bicycles we can use an array for them:​\\ ​
 +<code lb>
       NEW MyBikes(4) AS Bicycle       NEW MyBikes(4) AS Bicycle
  
Line 529: Line 554:
         END FUNCTION         END FUNCTION
       END CLASS       END CLASS
 +</​code>​
 There is one limitation of this technique: you cannot pass parameters to the constructor. The **default** constructor (a constructor with no parameters) will still be called however, and in the above program the necessary initialisation has been done there.\\ \\  There is one limitation of this technique: you cannot pass parameters to the constructor. The **default** constructor (a constructor with no parameters) will still be called however, and in the above program the necessary initialisation has been done there.\\ \\ 
 ===== Method Overloading ===== ===== Method Overloading =====
 \\  OOP languages commonly allow you to have multiple methods with the same name but with different **signatures**;​ in this context a '​signature'​ means the number of parameters and their types. LBB supports this too, although only the number of parameters is distinguished. One use for this facility is to have multiple constructors;​ which constructor is called will depend on how many parameters are specified in the NEW statement:​\\ ​ \\  OOP languages commonly allow you to have multiple methods with the same name but with different **signatures**;​ in this context a '​signature'​ means the number of parameters and their types. LBB supports this too, although only the number of parameters is distinguished. One use for this facility is to have multiple constructors;​ which constructor is called will depend on how many parameters are specified in the NEW statement:​\\ ​
 +<code lb>
       NEW MyVehicle1 AS Vehicle       NEW MyVehicle1 AS Vehicle
       NEW MyVehicle2 AS Vehicle 5       NEW MyVehicle2 AS Vehicle 5
Line 565: Line 592:
         END FUNCTION         END FUNCTION
       END CLASS       END CLASS
 +</​code>​
 Note that if you supply a **default** constructor,​ which takes no parameters, this will always be called, even if another constructor is called as well. Note that if you supply a **default** constructor,​ which takes no parameters, this will always be called, even if another constructor is called as well.
object_20oriented_20programming_20_28lbb_29.txt ยท Last modified: 2018/04/17 18:01 by tbest3112