Classes and Cups of Tea
I’ve never quite got my head around Classes. I know vaguely what they are (a definition of a group of variables and functions that acts like a kind of black box which can be defined and used in any way you like) and I know why they’re useful (the black box type of functionality means that someone can use a Class without knowing how the inner workings actually work, although the same can be said for functions. Plus there’s private name-spaces, inheritance, data and method encapsulation, readability etc. etc.).
Even so I’ve never found a reason to use them. This is probably because most of the programming I do is in PHP which is generally rendered one page at a time – there are no real-time events being triggered (generally clicking a button or link requests a new page meaning the start of a new procedure or maybe the re-running of the same procedure with altered variables) and at the scale of sites I’ve been working on I haven’t had any data that’s been complex enough to need classes. (Well, maybe I have and I didn’t know it…maybe I could have written all my sites in half the time…somehow I doubt it).
If I was creating the next Facebook or Myspace or some other type of large-scale site, or if I was working with a large group of other programmers (at the moment I pretty much just work with two others) then I can see how Classes would make things easier. One person writes the class and makes it work, the other uses it and puts it to work – neither need to know what the other did.
Unfortunately one one of the programmers I work with has used classes for a section of the site we’re working on. So it’s time learn!
To this end I’ve created the CupOfTea class. It’s not the most neatly written of classes and as I learn I’ll no doubt come back and re-write it, but it’s highly commented and should be a fairly self-explanatory guide to the basics of classes.
[Edit: This could be re-written to make a whole lot more sense. I was writing it as I went along, using it to try various things out. I wouldn't recommend you use it as a basis for your tea making activities.]
<?php
class CupOfTea {
// Definitions:
//
// Class A structure of variables/properties and functions/methods.
// Object An instance of a class. A group of properties and methods.
// e.g. $myCupOfTea = new CupOfTea
// $myCupOfTea is an Object which is an instance of the Class CupOfTea
// Or in English: $myCupOfTea is a CupOfTea. Which makes sense.
//
// Methods Functions defined inside of a class
// Properties Variables defined inside of a class
//
// Public Can be accessed from anywhere in script (e.h. $obj->publicVar (from anywhere) OR $this->publicVar (from inside the class))
// Protected Can be accessed only from same class and access inherited class (only $this->protectedVar AND from other classes if they inherit this var)
// Private Can be accessed only from same class (only $this->privateVar and no other way)
// Static Can be accessed without an instance of the object being created. Cannot be accessed through the object (i.e. $object->$myStaticVar This would fail.)
// Both functions (methods) and variables (properties) defined inside the class can be declared as public, private, protected or static.
//
// Things not covered in this post:
// Object Interfaces
// Magic Methods
// Object Cloning
// Object comparison
// Type hinting
// Late Static bindings
// References
// Object Serialisation
// A load of other stuff
// Public property declaration including default value
public $milk = true;
public $sugars = 2; // default value
// var $sugars = 2; <-- this would do the same thing as the line above (i.e. public is default)
// Protected var because the only thing that can change it is the process itself (i.e. this class) AND extensions should be able to.
protected $is_ready = 'no';
// Private vars. Only accessible from inside the function
private $cup = 'A sturdy mug.';
private $water = 'Roughly 300ml of boiling water.';
private $spoon = 'A standard teaspoon.';
// Constants - we don't want anyone changing this - they'll stay constant always. One exception: we can change them in a class extension.
const teabags = 1;
const boiling_point = 100;
// Method - returns the number of teabags.
function showTeaBags(){
return self::teabags . "\n";
}
// Method - returns the amount of sugars. Different syntax.
public function getSugars() {
return $this->sugars;
}
// Constructor method - called when an instance is instantiated. Used for, well, whatever is needed when copnstructing an instanceof a class.
function __construct(){
print 'Time for a cuppa :)<br />';
}
// Destructor method - called when all references to an object are removed or it is explicitly destroyed.
function __destruct(){
print 'All done. Drink up!<br />';
}
// Lists out all the vars and their values. Includes private vars as it is being defined inside the class.
// This demonstrates the concept of using refering to a object as an array of variables, using the foreach function as you would with any other array.
function showAllVars(){
echo '<br />Showing all vars (including private):<br />';
foreach ($this as $key => $value){
print "$key => $value<br />";
}
}
// This method returns a cup of tea which doesn't really make sense as the object itself is supposed to be the cup.
function makeTea(){
// Note: I haven't figured out how to make PHP actually make me a cup of tea yet, so we'll have to make do with pseudocode.
echo 'Making tea...<br />';
// $this->cup += ($this->teabags * $a_teabag);
// $this->cup += boiling($water);
// sleep(30);
// $this->cup -= ($this->teabags * $a_teabag);
// $this->cup += ($this->sugars * $spoonful);
// if ($this->milk == true) {
// $this->cup += $milk;
// }
// stir($this->cup, $this->spoon);
echo 'Tea making complete!<br />';
$this->is_ready = true;
return $cup;
}
}
class MagicTea extends CupOfTea {
// this can be re-defined because it's inherited and public.
public $sugars = 5;
// Magic == Lots of caffiene.
const teabags = 2;
// We can do this on protected vars, too. But NOT private!
protected $isReady = 'almost';
}
// Create a new object which is an instance of the CupOfTea Class.
$nicecuppa = new CupOfTea();
// Use a Class Method to get the current number of sugars.
echo 'Num of sugars = ' . $nicecuppa->getSugars() . '<br />';
// the :: operator can be used to access constant, static or overridden properties or methods of a class.
// you use it to refer to the class definition itself (i.e. "CupOfTea" rather than "$nicecuppa", so it can't reference something that will change or which there could multiple values.)
echo 'number of teabags (constant) = ' . CupOfTea::teabags . '<br />';
echo 'number of teabags in magic tea (constant) = ' . MagicTea::teabags . '<br />';
// List all variables using the Class Method (i.e. the method defined inside the class)
$nicecuppa->showAllVars();
// List all public variables from outside the class
echo '<br />Show all public vars:<br />';
foreach ($nicecuppa as $key => $value){
print "$key => $value<br />";
}
// Make a cup of tea using the makeTea() Method.
// This is a bit confusing really. Really the Object $nicecuppa should BE the cup of tea and the maketea() function should prepare it.
// However, I'm just playing around. If you can write a better tea Class then go for it!
$afinishedcup = $nicecuppa->makeTea();
echo '<br />';
?>
The above monstrosity will display something like this:
Time for a cuppa :)
Num of sugars = 2
number of teabags (constant) = 1
number of teabags in magic tea (constant) = 2
Showing all vars (including private):
milk => 1
sugars => 2
is_ready => no
cup => A sturdy mug.
water => Roughly 300ml of boiling water.
spoon => A standard teaspoon.
Show all public vars:
milk => 1
sugars => 2
Making tea...
Tea making complete!
All done. Drink up!
Edit 1: Apparently using classes generally will make code that runs slower than its hard-coded/procedurally coded alternative. Speeds up development time though, and makes things a whole lot simpler. As with everythin in programming, it’s a tool for a job. Don’t use a screwdriver to hammer in nails.