Main Content

From Structured to Object Oriented Programming.

Archive - Originally posted on "The Horse's Mouth" - 2012-10-02 17:40:55 - Graham Ellis

Background

A frequent comment - "I'm very used to conventional / structured programming, but I'm now trying to learn about Object Orientation and I don't understand the idea and I get baffled by all the buzzwords I hear". And a request "Can you help me?"

Yes - I can help you. If you come on a course that introduces Python, Ruby or C++, you'll be taught about Object Orientation and I'll clear the fog for you. With languages such as PHP and Perl, Object Orientation is just one way to write your code, and I cover "OO" on Perl for Larger Projects and on Object Orientation in PHP. With Tcl, Object Orientation comes in the [Incr Tcl] extension, and if I know in advance I can cover it during an extra evening session on out Tcl Courses.

So - learn a new programming language with us, and we'll include Object Oriented principles within the course as appropriate - you'll leave with a thorough grounding in the principles, and how they're applied to the language you have learned.

But - what if you're not learning one of the languages we teach?. Well - I can still be of some (but rather more limited) help in introducing you to Object Orientation - indeed, I did just such a thing for "RA" one evening last week; I'll be happy to do the same for you - in essence, it's half a day's training, and I'll be happy to do it where there's a gap in my schedule.

Basic Detail (the technical stuff)

When you're dealing with data, you want to perform a number of operations on that data. Some things are sensible to do, and others would be rather silly.

Let's take an example - let's say I'm writing a program (or suite of programs - in real life, you usually have a whole load of programs to look after your information) that deals with tables - the things that you sit at in a restaurant, or in class. There are certain operations that you'll want to perform on tables, such as calculating the area, and working out how many guests you can sit at them for food service. And there are certain operations you could perform on the data associated with tables that would be nonsense - for example, you wouldn't want to work out the square root of the length of one of the sides ...

So - what I'm going to do is to write a named block of code (in structured programming terms, you'll be familiar with the name function or subroutine or perhaps procedure or even command or macro) which I can call, passing in my initial data parameters about a table. And I'm going to have that named block of code return something I can store into a variable. Taking Python as my language of demonstration, here's how the calling code may look:

  first = table(2100,900)

No need in Python to declare variable types (or anything line that), but I have already pulled in from a separate file (or coded into the top of the file that contains this call) a definition of what a table is.

Having defined a table, I can then pass it into other named blocks of code which perform calculations on it. So, for example, I can write:

  pt1 = first.getpeople()

which is going to call the piece of code named getpeople on the data that's contained in the variable called first.

Simple idea, isn't it? I can create a whole lot of different tables - after all, a restaurant with just one table isn't going to be particularly cost effective, is it? And within the code that I've not shown you (yet!) that defines what a table is, I can create lots of other named blocks of code that let me do things with that table data. But in each case, I'm only going to have to worry about how the code works the first time I write it - thereafter, I can keep re-using the same code in lots of different programs. That's really nothing different to real life - after all, if you go into a restaurant and ask for a table for four, you're unlikely to quiz the member of staff who seats you on how he knows that the table he takes you to seats four, rather than 3 or 6!

Let's now add some terminology .
• We'll call the code that's all about tables a class
• We'll call each of the functions / subroutines in the class methods
• We'll call each individual data member of the class (each table) an object
• We'll call the method that sets up each object in the first place a constructor method
• We'll call the variable into which we store the object returned by the constructor an instance variable
• We'll call the set of methods that the user can call the API or Application Programmer Interface
• and We'll call the act of hiding logic within methods in the class, so that the application programmer doesn't need to know about it, encapsulation.

Here's a diagram showing how those elements go together - there may be a few more terms on this, as it's the final diagram from all my work the other evening, and it shows not one but three objects.


To complete this first example, and show you a runnable program, I also need to define my class; here's a complete program, in Python, showing both the class and a sample program that uses it all in one:

  class table (object):
    def __init__(self,width,height):
      self.width = width
      self.depth = height
    def getpeople(self):
      edge = int(self.width / 830)
      otheredge = int (self.depth / 830)
      total = 2 * (edge + otheredge)
      return total
  
  # ---------- ABOVE here - definition of a table
  # ---------- BELOW here - example program code to test and use tables
  
  first = table(2100,900)
  second = table(1900,840)
  third = table(1200,1200)
  
  pt1 = first.getpeople()
  pt2 = second.getpeople()
  s3 = third.getpeople()
  
  print "We can seat",pt1,"and",pt2,"and",s3,"people"


I've chosen, for this example, to create several (actually three) table objects, with different dimensions for each of them, to show you how my code is able to keep three different widths and three different heights apart from each other; when I run the code, I get:

  munchkin:oos12 grahamellis$ python d2
  We can seat 6 and 6 and 4 people
  munchkin:oos12 grahamellis$


The logic which defines the table - above the comment lines in my code above - comprises two methods. In Python, the constructor method is known as __init__, and I've used it simply to store two data values. The second method, which I've called getpeople, actually calculates the number of people who can sit at the table on which the method is run, and returns that number. You'll note that the method hides the logic from the calling program below the comment lines; indeed the main application programmer need know nothing about the recommended table frontage required by each diner, nor that fact that diners cannot be wrapped around table corners.

Second Stage (the technical stuff)

Not all tables are equal - but some are more equal that others (Apologies to George Orwell, who in Animal Farm wrote "All animals are equal, but some are more equal than others).

We looked at rectangular tables in the example just above, and we were able to vary the two dimensions to perform calculations for different tables. The algorithms for the calculations were the same in each case, but the numbers - and thus the results - differed. But let's go a step further. We may have a round table. Now - some of the code / algorithms may be the same, but others may differ. One way we could write code for a round table would be to duplicate the code for our original table, and then modify the copy. That would work well initially, but then when we came to update the common sections of the code later, we would find that we had two - and perhaps by that time many more - copies. so we need something better.

Let's define a class of table just as we did before. But we'll then define a roundtable class in such a way that we say "a roundtable is a table but with the following extra methods / methods replaced". That way, we don't need to copy the code - we can just supply (in our roundtable class) a set of changes. And we can go on and do the same thing for a squaretable too, and perhaps for many other classes of table. Indeed, we arrange then in a hierarchy.

This diagram shows how we might build our classes into a tree, and it adds in some of the extra OO keywords that are added to describe the concepts.


Let's now see that extra terminology .
• We'll call a class that other classes are based on a base class.
• Another word for a base class is a parent class.
• We'll call a class that's built from another an extended class.
• and We'll say that an extended class inherits from a base class.
• We may also call our extended class a subclass as it will have fewer object members than the base class.
• Where we replace a method in a base class with alternative code in a subclass, we call it overriding a method.

Here's a complete piece of code in which I've defined three different types of tables

  class table (object):
    def __init__(self,width,height,material=""):
      self.width = width
      self.depth = height
    def getpeople(self):
      edge = int(self.width / 830)
      otheredge = int (self.depth / 830)
      total = 2 * (edge + otheredge)
      return total
  class roundtable (table):
    def __init__(self,diameter,material=""):
      self.diameter = diameter
    def getpeople(self):
      total = int (3.14159265 * self.diameter / 830)
      return total
  class squaretable(table):
    def __init__(self,width,material=""):
      self.width = width
      self.depth = width
  
  # ---------- ABOVE here - definition of a table
  # ---------- BELOW here - example program code to test and use tables
  
  first = table(2100,900)
  second = table(1900,840)
  third = squaretable(1200)
  fourth = roundtable(890)
  clump = [first,second,third,fourth]
  
  for tabby in clump:
    pat = tabby.getpeople()
    print "This table will seat",pat


I've set up a list of tables (of various types) and I've then looped through each of them in turn calling the getpeople method. There are actually two different methods of this name, and as the loop runs, the appropriate one will be run for a roundtable, or for any other sort of table. You'll note that there's no need within your code to tell which is which; provided that you've made available methods of the same name which perform the same logical operation, the language will work out which one it needs to run - even different ones different times round the loop. Gone is the eed for if / elseif / elseif / elseif / elseif / type coding.

One final piece of terminology ...
• The work we use to describe this selection of the appropriate method as the code runs is know as polymorphism.

And looking further ahead

There's a limit to what I should cover in a single lesson on Object Orientation; what I've shown you above covers the basic principles you'll need on day one, but there are many other concepts and terms that you're likely to come across on a course.
• Public, protected, package and private declarations
• Final methods
• Abstract classes
• Class and object / unbound and bound / static and dynamic methods
• Accessors and properties
• Autoloaders
• Destructors
• Serialising and unserialising objects / picking and shelving
• Overloaded methods
• Design Patterns
• Factories, Comparators and Singletons
• Mixins, Multiple Inheritance and Interfaces
These don't all apply in every language, but each has its place and its reason, and all together they make object oriented programming the "power programming" methodology for the future.