Programming Concepts: Object-oriented programming (OOP)

From Wikibooks, open books for an open world
Jump to navigation Jump to search

UNIT 3 - ⇑ Programming Concepts ⇑

← Programming paradigms Object-oriented programming (OOP) Pointers →


You can use the same class as a template to make (instantiate) many objects

Object oriented programming is a type of programming paradigm based around programming classes and instances of classes called objects. These can be objects that appear on the screen (e.g., pictures, textboxes, etc.) or are part of the programming (e.g. actors, connections, particles, etc.).

Classes[edit | edit source]

Structures are very similar to Classes in that they collect data together. However, classes extend this idea and are made from two different things:

  • Attributes - things that the object stores data in, generally variables.
  • Methods - Functions and Procedures attached to an Object and allowing the object to perform actions

Let's take a look at the following example:

class car
  private maxSpeed as integer
  public fuel as integer
  public sub setSpeed(byVal s as integer)
    maxSpeed = s
  end sub
  public function getSpeed() as integer
    return maxSpeed
  end function
  public sub refuel(byVal x as integer)
    console.writeline("pumping gas!")
    fuel = fuel + x
  end sub
  public function getFuel() as integer
    return fuel
  end function
  public sub drive()
    fuel = fuel - 1
  end sub
end class

You can see that the class is called car and it has:

  • two attributes: maxSpeed, fuel
  • five methods
    • three procedures: setSpeed, refuel, drive
    • two functions: getSpeed, getFuel

Remember this is a class and therefore only a template, we need to 'create' it using an object

Attributes[edit | edit source]

These store information about the object. In the example above we store the fuel and maxSpeed. The attributes are attached to the classes, and if there are several instances (objects) of the classes then each will store its own version of these variables. Note that instead of the usual dim, there is the word private or public, we'll cover that in the encapsulation section.

Methods[edit | edit source]

Unlike structures, OOP allows you to attach functions and procedures to your code. This means that not only can you store details about you car (the attributes), you can also allow for sub routines such as drive() and refuel, which are attached to each class.

Exercise: Object Orientation Intro
What is the difference between a class and an object?

Answer:

  • A class is a template which cannot be executed
  • An object is an instance of a class which can be executed
  • one class can be used to make many objects
What are the main components of a class?

Answer:

methods and attributes

What is the difference between a structure and a class

Answer:

structures don't have methods

OO - PIIE[edit | edit source]

When talking about OOP you must remember the following:

00 - PIIE!

Where:

  • 00 = Object Orientation and
  • PIIE = Polymorphism / Inheritance / Instantiation / Encapsulation


Instantiation[edit | edit source]

As we have seen a class is a template for something, you can't actually execute a class, you must instantiate it, that is create an instance of an class in the form of an object.

dim polo as new car   'instantiation 1
dim escort as new car 'instantiation 2

The code above creates an object called polo and escort, both of class type car (which we declared earlier). We can now use all the public attributes and methods:

polo.refuel(100) 'assuming fuel starts at 0
polo.drive()
escort.refuel(50) 'assuming fuel starts at 0
escort.drive()
for x = 1 to 20
  escort.drive()
  polo.drive()
next
polo.refuel(10)
console.writeline("polo: " & polo.getFuel())
console.writeline("escort: " & escort.getFuel())

This would output the following:

   Code Output

pumping gas!
pumping gas!
pumping gas!
polo: 89
escort: 29


Exercise: Instantiating a car
Write your own instantiation for a beetle car:

Answer:

dim beetle as new car 'instantiation

What would the following output:

dim ka as new car
dim montego as new car
ka.refuel(10) 'assuming fuel starts at 0
montego.refuel(50) 'assuming fuel starts at 0
montego.drive()
montego.drive()
for x = 0 to 10
  montego.drive()
next
ka.refuel(10)
console.writeline("ka: " & ka.getFuel())
console.writeline("montego: " & montego.getFuel())

Answer:

   Code Output

pumping gas!
pumping gas!
pumping gas!
ka: 20
montego: 37

Encapsulation[edit | edit source]

You can only access private attributes and methods through an interface (public methods)

You noticed that we didn't have to use the dim statement for the attributes and we used the word private instead. What this means is that these attributes are not directly accessible once you have instantiated the class. Let's take our polo class as an example:

polo.fuel = 100 'this would be acceptable (but not in the exam!)

In the example we access the fuel attribute of the polo class and give the car 100 units of fuel because fuel is declared as public, there are no restrictions in accessing it. However, when we try the following we run into trouble:

polo.maxSpeed = 100 'this would be unacceptable

The reason that this wouldn't work is because we have declared the maxSpeed attribute as private. If something is declared as private you can't access it externally, but how do you access it? The only way to access a private method or attribute is to use an interface, or public method. In the car code example we have:

public sub setSpeed(byVal s as integer) 'declaring an interface
   maxSpeed = s
end sub

Because this method is public we can call it through: polo.setSpeed(100). And because setSpeed is declared inside the car object, it can have access to all the private attributes and methods.

We also need to find out the speed of a car to display to the user, we can do this by creating a get routine:

public function getSpeed() 'declaring an interface (a function as we are returning a value)
   return maxSpeed
end function

Because this method is public we can call it through: polo.getSpeed(). And because getSpeed is declared inside the car object, it can have access to all the private attributes and methods.

In general attributes should always be declared as private and only accessible through interfaces, using a setX command to give the private variable X a new value, and using the getX command to return the value of X. You should never directly access X!

Exercise: Encapsulation

Declare a colour attribute for the car that can only be accessed through an interface

Answer:

private colour as string 'this must be private!
Write an interface to set the colour

Answer:

public sub setColour(byVal c as string) 'declaring an interface, make sure it's public!
   colour = c
end sub
Write an interface to return the colour

Answer:

public function getColour() 'it must be a function to return a value
   return colour
end function
Create an actor class with the following:
  • attributes: health, dexterity, x, y, strength
  • methods: walkforward(), eat(), gethit(), displaystats(), setHealth(p), setLocation(px,py)

Answer:

Class actor
 Private health As Integer
 Private name As String
 Private x As Integer
 Private y As Integer

 Public Sub setName(ByVal p)
  name = p
 End Sub

 Public Sub walkforward()
  x = x + 1
 End Sub

 Public Sub eat()
  health = health + 10
  Console.WriteLine("Nom Nom Nom")
 End Sub

 Public Sub gethit()
  health = health - 10
  Console.WriteLine("Argh!")
 End Sub

 Public Sub displaystats()
  Console.WriteLine("Character :" & name)
  Console.WriteLine("Health :" & health)
  Console.WriteLine("Location :" & x & ", " & y)
 End Sub

 Public Sub setHealth(ByVal p)
  health = p
 End Sub

 Public Sub setLocation(ByVal px, ByVal py)
  x = px
  y = py
 End Sub

End Class
For the actor class declared above instantiate:
  • Wizard called Barry with 100 Health starting at 4,5
  • Orc called Herbert with 35 Health starting at 20,2, then report on his status

Answer:

dim wizard as new actor  'it doesn't have to be named wizard, it could have another name
dim orc as new actor     'it doesn't have to be named orc, it could have another name

wizard.setName("Barry") 'remember to use your get and set routines!
wizard.setHealth(100)
wizard.setLocation(4,5)

orc.setName("Herbert")
orc.setHealth(35)
orc.setLocation(20,2)
orc.displaystats()
Programming Get and Set Routines

Encapsulation is such a common thing that some languages have short cuts for making get and set routines. In VB.NET this involves using a property:

Private _fuel As Integer

Public Property Fuel() As Integer
    Get
        Return _fuel
    End Get
    Private Set(ByVal value As Integer)
        _fuel = value
    End Set
End Property

As we will never call _fuel directly it doesn't matter that it has an underscore at the beginning. Using this code we can perform the following methods without having the fuel attribute as public:

lada.fuel = 23
Console.Writeline(lada.fuel)

Inheritance[edit | edit source]

inheritance diagram of vehicles, all sharing attributes and functions from the parent class 'Vehicle'. Note the direction of arrows

Building on the car example above, what would happen if we wanted to declare an electric car? Well we'd probably want to store some information on the number of batteries that it has:

class electricCar
  private maxSpeed as integer
  private fuel as integer 'fixed!
  private numBatteries as integer 'added
  public sub setnumBatteries(byVal n as integer)
    numBatteries = n
  end sub
  public function getnumBatteries()
    return numBatteries
  end sub
  public sub setSpeed(byVal s as integer)
    maxSpeed = s
  end sub
  public function getSpeed() as integer
    return maxSpeed
  end function
  public sub refuel(byVal x as integer) as integer
    '.....
  'HOLD ON! 
end class

This seems like a very long and tedious task rewriting all the same code again. You're right! It would be far better if we only had to declare all the new stuff we wanted to add. OOP allows for inheritance, where a new class can inherit the attributes and methods of a parent class:

class electricCar
  inherits car 'declares what attributes and methods you are inheriting
  private numBatteries as integer 'added
  public sub setnumBatteries(byVal n as integer) 'interface
    numBatteries = n
  end sub
  public function getnumBatteries() 'interface
    return numBatteries
  end function
end class

This means that everything that car declared is now accessible from electricCar, as well as the new numBatteries attribute and methods. Let's instantiate this example and see what's possible

dim gwiz as new electricCar
gwiz.setnumBatteries(6) 'from electricCar
gwiz.setSpeed(60)       'from car
gwiz.drive()            'from car

By using inheritance it makes creating new classes very quick and easy. It also allows for a modular approach to creating classes, where you might never use the base class at all, but only as a means of creating other child classes.

Rather than having to rewrite the same functionality for similar objects, OOP allows you to reuse attributes and methods from parent classes.

Exercise: Inheritance
Declare a new class called limo that has attributes numSeats and colourSeats; and the ability to interface with them

Answer:

class limo
  inherits car 'declares what attributes and methods you are inheriting
  private numSeats as integer 'must be private
  private colourSeats as integer 'must be private
  public sub setnumSeats(byVal s as integer) 'interface set
    numSeats = s
  end sub
  public function getnumSeats() 'interface get
    return numSeats
  end function
  public sub setcolourSeats(byVal c as string) 'interface set
    colourSeats = c
  end sub
  public function getcolourSeats() 'interface get
    return colourSeats 
  end function
end class
What are the benefits of using inheritance?

Answer:

Creating new classes from parent classes is very quick and easy. It allows for a modular approach to creating classes, where you might never use the base class at all.

Inheritence diagrams[edit | edit source]

CPT-OOP-inheritance.svg
inheritance diagram of vehicles, all sharing attributes and functions from the parent class 'Vehicle'.
  • The Truck inherits the Vehicle and adds its own attributes and methods
  • The Car inherits the Vehicle and adds its own attributes and methods
  • The Electric inherits the Car (and therefore the Vehicle) and adds its own attributes and methods
  • The Petrol inherits the Car (and therefore the Vehicle) and adds its own attributes and methods

Note the direction of arrows, you'll get marked down for putting them in the wrong direction.

Exercise: Inheritance Diagrams

What is the parent class of car in the above diagram?

Answer:

vehicle
Draw an inheritance diagram for the following classes:
motor bikes, bikes, vehicles, pedal bikes, trikes.

Answer:


Draw an inheritance diagram for the following classes:
Monster, Character, Dragon, Hero, Orc

Answer:


Polymorphism[edit | edit source]

When you were young you might have watched the Mighty Morphin' Power Rangers. These guys could morph from regular people into their power suits. Sadly polymorphism isn't that exciting, but it does allow you to change the function of attributes and methods when you are inheriting from a parent class. Consider our car example again. When we created the electricCar object we inherited from car and added the numBatteries attribute and methods. But what happens when we try and refuel, let's take a look at the code:

public sub refuel(byVal x as integer) as integer
  console.writeline("pumping gas!")
  fuel = fuel + x
end sub

Well this just won't do. We are creating an electric car and we don't want to say that we are pumping gas; what would our sandal-socked yoghurt eating friends say! So for the electricCar object we want to inherit everything from car, but we want to morph(change) the refuel method. To do that we are going to use something called override:

class electricCar
  inherits car
  private numBatteries as integer
  public sub setnumBatteries(byVal n as integer)
    numBatteries = n
  end sub
  public function getnumBatteries() as integer 'interface
    return numBatteries
  end sub
  '###### overrides morphs the inherited version, replacing it
  public overrides sub refuel(byVal x as integer)
    console.writeline("pure renewable energy!")
    fuel = fuel + x
  end sub
  '######
end class
Exercise: Polymorphism
In polymorphism what is the keyword we use to redefine a subroutine:

Answer:

overrides

Write a definition of a limo class that uses polymorphism that makes sure that the maxSpeed never goes beyond 100:

Answer:

class limo
  inherits car
  public overrides sub setSpeed(byVal s as integer)
    if s > 100 then
      maxSpeed = 100
    else
      maxSpeed = s
    end if
  end sub
end class
Write a definition of musclecar that inherits car, but uses 30 units of fuel per drive and displays "vroom vroom!" every time it drives. It should also store details on leatherSeating, allowing you to interface with this.

Answer:

class musclecar 
  inherits car
  private leatherSeating as boolean
  public overrides sub drive()
    fuel = fuel - 30
    console.writeline("vroom vroom!")
  end sub
  public sub setLeather(s as boolean)
    leatherSeating = s
  end sub
  public function getLeather()
    return leatherSeating
  end function
end class
Describe polymorphism

Answer:

Polymorphism allows you to inherit attributes from a parent class, but redefine some of the methods or attributes