Mr Chimp Learns to Write

if (!$geek) { header('Location:http://google.com'); }

Classes and Cups of Tea

leave a comment »

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.

Written by Mr Chimp

October 12th 2009 at 5:08 pm

Posted in Uncategorized

Tagged with , , ,

Leave a Reply