| « My so-called standoffish kitten | New Year's Resolutions » |
Sun, Jan 16, 2011
![[Icon]](rsc/img/chain_link.gif)
So I've played around with Python, and then with PHP, and now Perl. All three can be used for object-oriented programming.
A while ago, when I was trying to learn more PHP, I started to feel the lack of knowledge about its OOP aspect. Having started out with K&R's book on C, procedural logic has always made sense to me: What was this object thing?
So I googled around for a while, and what I basically came up with was.. nothing. Not a thing. No matter how I looked, I could never find a clear, simple explanation of just what object-oriented programming IS.
So I thought I might have a go at explaining it myself.
Executive summary: Objects are just variables that can process data as well as store it.
To expand: Let's imagine a vet who wants to upgrade from paper records to a computer system. This involves writing some code to handle record-keeping.
So, we sit down and write some code. Naturally, the code needs to be able to handle data, and we store this in variables: Essentially, this is just a name given to a place in the computer's memory where data can be stored.
So we start out simply: What do our records need? Well, we want to store the animal's name, its species, it's date of birth, and its owner's details.
In our program, we therefore have $pet_name, $owner_name, $pet_dob, and $pet_species.
And that works fine. Except that, as the codebase gets larger and larger, having all these separate variable names gets to be a bit of a headache. Not only is it a lot of typing, but sometimes you can forget to update one variable when you update others, giving results such as a parrot named Fido and a pitbull named Mittens. And sometimes we want to have TWO animals' details loaded at once, and then we have to duplicate all those variable names for animal 1 and animal 2.
It would be nice if we could have one single record with *all* the data in it, and eliminate all these problems.
Enter the array: A single variable that can hold multiple values, in a nice orderly list. We replace the multiple independent variables $pet_name, $owner_name, $pet_dob, and $pet_species with a single array. Pet name is now $pet[0], owner name is $pet[1], birthdate is $pet[2] and species is $pet[3]
Beautiful and simple, and this works okay for a while. But time goes by and those numbers start to get hard to remember when we come back to the code after a break: Sometimes we use the wrong number and start sending emails to Mr. Dog regarding Benji, his pet seventh of July.
So we want something a bit more meaningful than a number to access our information, and this is where the hash table comes into play. Like an array, it's a single variable that can hold multiple pieces of data. But unlike an array, it is unordered, and data is accessed by name instead of number.
We update the codebase, and now we have $pet{name}, $pet{owner}, $pet{dob}, and $pet{species}. And that's all wonderful and does everything we need.
But as the code grows ever bigger, we start to find a lot of replication in our code - redundancies abound as the same calculations have to be done in multiple places. Our main problem is the pet's age: This obviously can't be stored as a number on the database, because it's not a static number. But we need to call it in multiple places: Vaccinations, neutering, routine checkups, etc. etc. It would be nice if the pet's age could be accessed via the variable, instead of having to get the age and then work out the age each time it's needed.
Enter the object. Like our other variables, this can store data. But it can also have methods assigned to it. So we replace our pet hash tables with pet objects, and now we have $pet->name, $pet->owner, $pet->dob, and $pet->species - methods that do nothing but get or set the data. But we also set up $pet->age, a method that subtracts the pet date of birth from today's date and so returns the correct age.
The beauty of the object concept is that it abstracts processes: $pet->dob just gets information from the database, whereas $pet->age performs a calculation to return dynamic data. But both are called in the same way, and you don't ever have to care about where the data comes from or what's done to it: It's just data that you call when you need it.
What's more, objects can inherit their definitions from one or more other types of object. Let's say that you have four types of animal: Cat, dog, bird, and reptile. Every single one of them is a pet, and they will all have owners, a date of birth, a name, and a species. Great. We have data fields set up for those in $pet
But cats and dogs need vaccinations and boosters, whereas reptiles and birds don't. So we set up four new types of object, or "class". But we don't have any redundant code, specifying repeatedly a $dog->dob, $cat->dob etc.
No, we just set all four classes to inherit from the $pet definition, and it all Just Works. We then add a few extra data types to $dog and $cat - neutered, vaccination_date, booster_date and fur_colour.
And that's great, but then we think actually, we should be keeping the animal's history in their records as well. So now, we can add previous_conditions to the $pet definition, which all four other classes inherit from, and instantly all four types are updated to have the new history field in them.
Then we think, hey, booster dates are calculated based on vaccination dates. So instead of booster_date being something that the vet works out in their head and then enters manually, let's change it to be a method that looks at vaccination_date and works out the right date on its own.
So we go ahead and do this. And because it's all abstracted into the object, we don't need to change *any* of the code that refers to the booster date: We needed to call $dog->booster_date when the date was manually entered into the database; we now need to call $dog->booster_date when it's calculating the date on the fly.
So, in summary:
It's worth knowing that objects can inherit from other objects, and that methods are abstracted away from the code, and all that. Of course it is. But it's only worth knowing all that when you've already got an answer to what an object *is* in the first place.
When other people have sat down and written guides to OOP, they've thought "What do people need to know?" and so they've thrown out terms like inheritance, polymorphism, and god knows what else. I've tried to approach it from the other side, and hopefully it's made some sense.
Feedback is always welcome..
![[Links]](http://geekblog.oneandoneis2.org/skins/112/rsc/img/chain_link.gif)
I'm in the Perl newsletter again. I should try and write about some other language...
21/05/12
Facebook Syndication Error
22/05/12
![]()
I last listened to:
Johann Pachelbel - Canon in D major
Most recent photo:
js.js