Hi @ChrisBull -
I have struggled quite a bit in this area myself.
I am no expert, but hopefully I can help your understanding some. In my experience, I didn't start to understand the necessity of static methods, abstract classes, and interfaces until I started working on multiple projects at a time which were
similar, but not the same.
Important Note: I rarely start building a static method, abstract class, or interface from the start (well now I do, but it's taken a while). More commonly, I realize that a regular class that I have spent some time constructing can be modified or re-factored into these things, and I try my best to do so, because I'll thank myself when working on future projects.
Static Methods
I typically realize I need to turn a method into a static method when I realize that it does something really useful that I need in numerous places
outside of the class or in
sub-classes of the class. For example, I have a function that "swaps" two array values:
Code: Select all
//Sill class name just for the example
class MyClass
{
//This method "swaps" or "exchanges" the value at $list[$indexA] with the value at $list[$indexB]
public static function swap($list, $indexA, $indexB)
{
$valueA = $list[$indexA];
$list[$indexA] = $list[$indexB];
$list[$indexB] = $valueA;
return $list;
}
}
I would use the above class like this:
Code: Select all
//Here is a list (array) of values
$myList = array('first', 'second', 'third', 'fifth', 'sixth', 'fourth');
//I need to swap the 'fifth' and 'fourth' string values
//Call the 'swap' function
$list = MyClass::swap($myList, 3, 5);
A couple points about the `swap()` method above:
- It is "generic", meaning it does not contain any unique values, data, or usage. It is a general use method that can be used on any array to swap any two of that array's values. So, if I store `MyClass` in a single directory on my computer, I can include that class in many different projects where I would need to swap two array values.
- It takes only one line of code to call the `MyClass::swap()` method, instead of multiple lines, which a non-static, public method would take (Example below)
Here is a non-static version of the `swap` method above:
Code: Select all
class MyClass2
{
public function swap($list, $indexA, $indexB)
{
$valueA = $list[$indexA];
$list[$indexA] = $list[$indexB];
$list[$indexB] = $valueA;
return $list;
}
}
The above "non-static" version of the `swap()` method is cumbersome in use, as it will take two lines to use it:
Code: Select all
//You have to create an instance of the MyClass2 class first:
$myClass2Instance = new MyClass2();
//After MyClass2 has been instantiated, then you can call the `swap()` method:
$list = $myClass2Instance->swap($list, 3, 5);
While it may seem trivial in this example, the extra line of code
just so I can use my swap() method is aggravating during development, especially when I might need that method in numerous places in one project.
Abstract Classes
I often realize after I have written a class that is specific to a current problem/project that I can make an abstract version of it. So, if I can't figure out how to write a useful abstract class when I start a project, I just start working on the project with the intent to abstract the classes at a later time.
Abstract classes are truly incredible, but in my opinion, they shine mostly when I am working on large projects. It is important to note that I currently work independently, so I don't work with a team, but I understand that abstract classes also really shine when working on a team. I have come to realize, though, that working independently is like working with different people (my past, present, and future self). This is because, after I work on a project, let's call it project "A", then, a few days later, I have to switch mental gears and work on project "B", and then a few days later work on project "A" again, it is often like looking a totallly different individual's work when I return to that first project at a later time. Abstract classes have helped me to clarify the
usage and
intent of classes when I have not worked on a project in a while and don't have time or energy to read the code line-by-line to figure it out.
Okay, on to an example...
Recently, I have been using PHP to write some content management systems for websites which have multiple pages, each with different and unique content (how novel, I know

). Now, it would be tedious, easy to make errors, and time-wasting to have to re-write or copy and paste the same chunks of HTML code on every single page of the website. And, when I moved on to another, similar, website project, I'd have to start this tedious process all over again. The solution here is an abstract class. I sat down and thought about every part of a basic HTML page that would be needed on
every (or most) of the pages in my current project. I then created an abstract class that contained these re-usable chunks of HTML, with the intent to sub-class this abstract class on each unique page.
Here is an example (really simplified for this example) of an abstract HTML page:
Code: Select all
//Notice the `abstract` keyword.
//Also, I always prepend my abstract class names with an A, as a message to myself that the class is abstract
abstract class AHTMLPage
{
protected $title;
//meta() is intended to be overridden in sub-classes and called within the head() method
//You could use it to include project-specific references to JavaScript and CSS files in the <head> section of your HTML
abstract protected function meta();
//head() is intended to be overridden in sub-classes with project-specific HTML code
abstract protected function head();
//body() is intended to be overridden in sub-classes with project-specific HTML code
abstract protected function body();
//foot() is intended to be overridden in sub-classes with project-specific HTML code
abstract protected function foot();
//This is the method that you can use to display your HTML page
public function display()
{
$this->head();
$this->body();
$this->foot();
}
}
Now, one point about the `AHTMLPage` class above is that it is useless on it's own. I made it
very generalized and I think of it as a template for projects that require HTML pages.
Now, I will start to get more specific and sub-class AHTMLPage for a specific project:
Code: Select all
class CarMechanicWebsiteHTMLPage extends AHTMLPage
{
//Notice I do not need to re-write the class property `$title`, it is inside of the AHTMLPage parent class and, since it is not private, is accessible to this class
//Constructor method to define the $title property
public function __construct($title)
{
$this->title = $title;
}
//Use this to describe CSS and JavaScript references
protected function meta()
{
?>
<link type="text/css" src="css/style.css" media="screen" />
<?php
}
//This method overrides the AHTMLPage::head() method, meaning it takes precedence over the one in AHTMLPage.
protected function head()
{
?>
<html>
<head>
<title><?php echo $this->title; ?></title>
</head>
<body>
<div id="header">
<h1>Car Mechanic Website</h1>
<p>Located on Some Street, in Baltimore, MD.</p>
</div>
<div id="main">
<?php
}
//Notice I do not override AHTMLPage::body() in this class. I will do so in another sub-class
//foot() is overriding AHTMLPage::foot()
protected function foot()
{
?>
</div>
<div id="footer">
<p>Copyright © 2010, Michael T. Moore, All Rights Reserved. http://www.miketmoore.com</p>
</div>
</body>
<?php
}
//No need to override AHTMLPage::display(), since I'll use it as is
}
Code: Select all
class StartPage extends CarMechanicWebsiteHTMLPage
{
protected function body()
{
?>
<h2>Welcome to Car Mechanic Website</h2>
<p>Relevant info about us here.</p>
<?php
}
}
That's it! Now, to display the StartPage class I do this:
Code: Select all
$htmlPage = new StartPage();
$startPage->display();
I will only need to override the body() method for each unique page of the Car Mechanic website. I will be saved from writing tons of the same HTML over and over again. This also ensures that less errors in typing the HTML occur.
Well, I don't have enough steam to continue on with interfaces. Hopefully that helps some!