Difference between revisions of "Getting Started with Object Oriented Programming"

From Joomla! Documentation

m (None)
(Add scope modifiers to functions)
(4 intermediate revisions by 3 users not shown)
Line 1: Line 1:
PHP is an object oriented language, and to use the MVC structure as implemented by Joomla!, a solid understanding of object oriented programming ''(OOP)'' is required. This document explains the reasons for using objects and the way objects are used in PHP.
+
PHP is an object oriented language, and to use the MVC structure as implemented by Joomla!, a solid understanding of object oriented programming ''(OOP)'' is required. This document explains the reasons for using objects and the way objects are used in PHP and Joomla.
  
 
== Introduction to Objects ==
 
== Introduction to Objects ==
Line 5: Line 5:
 
As we venture into object oriented programming, it is important to note that it is called 'object' oriented for a reason.  
 
As we venture into object oriented programming, it is important to note that it is called 'object' oriented for a reason.  
  
Before object oriented programming (OOP), everything was based on ''functions'' and ''variables''. Let's consider an application that calculates a person's BMI. You might have three variables: <code>$height</code> and <code>$weight</code> and <code>$name</code>. These variables would be used to store a person's name, height and weight. You might then have a function called <code>calculateBMI()</code>, which would accept as parameters $height and $weight.   
+
Before object oriented programming (OOP), everything was based on ''functions'' and ''variables''. Let's consider an application that calculates a person's BMI. You might have three variables: <code>$height</code> and <code>$weight</code> and <code>$name</code>. These variables would be used to store a person's name, height and weight. You might then have a function called <code>calculateBMI()</code>, which would accept as parameters $height and $weight.   
  
 
This would look something like:
 
This would look something like:
  
&lt;source lang="php">
+
<syntaxhighlight lang="php">
function calculateBMI( $height, $weight ) {
+
public function calculateBMI( $height, $weight ) {
 
     return $weight / $height;
 
     return $weight / $height;
}&lt;/source>
+
}</syntaxhighlight>
  
 
But it is very easy to lose track of all these variables in the code, not to mention the fact that only one person is supported at a time. The idea behind objects is to '''encapsulate''' this data '''and''' the functions to manipulate it into one ''package''. The definition of this package is called a ''class''.
 
But it is very easy to lose track of all these variables in the code, not to mention the fact that only one person is supported at a time. The idea behind objects is to '''encapsulate''' this data '''and''' the functions to manipulate it into one ''package''. The definition of this package is called a ''class''.
Line 18: Line 18:
 
So we might have:
 
So we might have:
  
&lt;source lang="php">
+
<syntaxhighlight lang="php">
 
class person
 
class person
 
{
 
{
     var $name;
+
     public $name;
     var $height;
+
     public $height;
     var $weight;
+
     public $weight;
  
     function getBMI() {
+
     public function getBMI() {
 
         return $this->weight / $this->height;
 
         return $this->weight / $this->height;
 
     }
 
     }
}&lt;/source>
+
}</syntaxhighlight>
  
 
Then, if you want to create an object which represents a person, you would do:
 
Then, if you want to create an object which represents a person, you would do:
  
&lt;source lang="php">
+
<syntaxhighlight lang="php">
 
$person = new person();
 
$person = new person();
&lt;/source>
+
</syntaxhighlight>
  
 
This is called ''instantiating'' the class, because it creates an ''instance'' of the class (an object described by the class).
 
This is called ''instantiating'' the class, because it creates an ''instance'' of the class (an object described by the class).
Line 40: Line 40:
 
Now, you can modify the variables (which are called ''properties''), using:
 
Now, you can modify the variables (which are called ''properties''), using:
  
&lt;source lang="php">
+
<syntaxhighlight lang="php">
 
$person->height = 2;
 
$person->height = 2;
 
$person->weight = 50;
 
$person->weight = 50;
&lt;/source>
+
</syntaxhighlight>
  
 
Then you can invoke its functions (which are called ''methods'') using:
 
Then you can invoke its functions (which are called ''methods'') using:
  
&lt;source lang="php">
+
<syntaxhighlight lang="php">
 
$bmi = $person->getBMI();
 
$bmi = $person->getBMI();
&lt;/source>
+
</syntaxhighlight>
  
Often, many classes are similar, but too different to put into one class. For example, all animals have lungs, and because humans and cats are animals, they could both have a &lt;code>$lung_capacity&lt;/code>. However, cats have tails, so should an &lt;code>Animal&lt;/code> class have a &lt;code>$tail_length&lt;/code>? No, that is not necessary. You can make a class a ''subclass'' or ''child class'' of another, essentially stating that the subclass has everything its parent class has, plus some extensions.
+
Often, many classes are similar, but too different to put into one class. For example, all animals have lungs, and because humans and cats are animals, they could both have a <code>$lung_capacity</code>. However, cats have tails, so should an <code>Animal</code> class have a <code>$tail_length</code>? No, that is not necessary. You can make a class a ''subclass'' or ''child class'' of another, essentially stating that the subclass has everything its parent class has, plus some extensions.
  
 
In Joomla, most classes are children of JObject. Now, if we were to make person a child class of JObject, then we would ''inherit'' the capabilities of the JObject class. We would then change the definition to something like:
 
In Joomla, most classes are children of JObject. Now, if we were to make person a child class of JObject, then we would ''inherit'' the capabilities of the JObject class. We would then change the definition to something like:
  
&lt;source lang="php">
+
<syntaxhighlight lang="php">
  
 
class person extends JObject
 
class person extends JObject
 
{
 
{
     var $name;
+
     public $name;
     var $height;
+
     public $height;
     var $weight;
+
     public $weight;
  
     function getBMI() {
+
     public function getBMI() {
 
         return $this->weight / $this->height;
 
         return $this->weight / $this->height;
 
     }
 
     }
 
}
 
}
&lt;/source>
+
</syntaxhighlight>
  
Then we could ''manipulate'' our person using the &lt;code>get()&lt;/code> and &lt;code>set()&lt;/code> methods that JObject has:
+
Then we could ''manipulate'' our person using the <code>get()</code> and <code>set()</code> methods that JObject has:
  
&lt;source lang="php">
+
<syntaxhighlight lang="php">
 
$person->set( 'name', 'Bob' );
 
$person->set( 'name', 'Bob' );
 
$person->set( 'height', 2 );
 
$person->set( 'height', 2 );
Line 77: Line 77:
 
$person->get( 'weight' );
 
$person->get( 'weight' );
 
echo $person->getBMI();
 
echo $person->getBMI();
&lt;/source>
+
</syntaxhighlight>
  
You will notice the use of &lt;code>$this&lt;/code> inside classes a lot. &lt;code>$this&lt;/code> is a reference to the '''current''' object. So if I am inside a class, and I use say &lt;code>$this->height = 2;&lt;/code>, then that means I am setting the property 'height' of the current object to 2. When we use &lt;code>$this->height&lt;/code>, we aren't talking about any height, but we're talking about the current object height.
+
You will notice the use of <code>$this</code> inside classes a lot. <code>$this</code> is a reference to the '''current''' object. So if I am inside a class, and I use say <code>$this->height = 2;</code>, then that means I am setting the property 'height' of the current object to 2. When we use <code>$this->height</code>, we aren't talking about any height, but we're talking about the current object height.
  
 
== More on Objects ==
 
== More on Objects ==
Line 87: Line 87:
 
So, I might have a class called copier. Now, what operations do I generally need to do with a copier? Well, the basic functionality I need is copy functionality. So I need a method called 'copy':
 
So, I might have a class called copier. Now, what operations do I generally need to do with a copier? Well, the basic functionality I need is copy functionality. So I need a method called 'copy':
  
&lt;source lang="php">
+
<syntaxhighlight lang="php">
 
class Copier
 
class Copier
 
{
 
{
     function copy() {
+
     public function copy() {
 
         echo 'One copy made';
 
         echo 'One copy made';
 
     }
 
     }
 
}
 
}
&lt;/source>
+
</syntaxhighlight>
  
 
Now, this is a very basic copier. What if I wanted to extend the functionality of my Copier? Well, to extend the functionality, I create a child class. ''A child class will inherit all the functionality of the parent class.''
 
Now, this is a very basic copier. What if I wanted to extend the functionality of my Copier? Well, to extend the functionality, I create a child class. ''A child class will inherit all the functionality of the parent class.''
Line 102: Line 102:
 
So here is our child class:
 
So here is our child class:
  
&lt;source lang="php">
+
<syntaxhighlight lang="php">
 
class CopierWithCounter extends Copier
 
class CopierWithCounter extends Copier
 
{
 
{
     var $counter;
+
     public $counter;
  
     function copy() {
+
     public function copy() {
 
         $this->counter++;
 
         $this->counter++;
 
         parent::copy();
 
         parent::copy();
 
     }
 
     }
 
}
 
}
&lt;/source>
+
</syntaxhighlight>
  
So we now have a property called &lt;code>$counter&lt;/code> that keeps track of the number of copies made. Notice that the method we defined has the same name as the method in the Copier class. What this means is that we don't need to learn anything new to use the copier - it behaves in the same way as our old copier, but it just keep track of the number of copies.
+
So we now have a property called <code>$counter</code> that keeps track of the number of copies made. Notice that the method we defined has the same name as the method in the Copier class. What this means is that we don't need to learn anything new to use the copier - it behaves in the same way as our old copier, but it just keep track of the number of copies.
  
You will see that inside of the &lt;code>copy()&lt;/code> method there is a line: ''&lt;code>parent::copy()&lt;/code>''. The &lt;code>parent&lt;/code> keyword references the parent class, which is in this case Copier.  So this line will invoke the &lt;code>copy()&lt;/code> method of the Copier class. In this way, we don't have to rewrite the functionality to make a copy - we have already done that in the Copier class.
+
You will see that inside of the <code>copy()</code> method there is a line: ''<code>parent::copy()</code>''. The <code>parent</code> keyword references the parent class, which is in this case Copier.  So this line will invoke the <code>copy()</code> method of the Copier class. In this way, we don't have to rewrite the functionality to make a copy - we have already done that in the Copier class.
  
 
So we have the exact same functionality as the Copier class, except that anytime a copy is made it will increment the $copies property by 1. Just as in real life, the addition of the counter doesn't change the way that I use the copier - I don't need to know anything about the counter to just make a simple copy.
 
So we have the exact same functionality as the Copier class, except that anytime a copy is made it will increment the $copies property by 1. Just as in real life, the addition of the counter doesn't change the way that I use the copier - I don't need to know anything about the counter to just make a simple copy.
  
Now, the question arises: what value does &lt;code>$counter&lt;/code> have to start with? We know that it increases by one every time a copy is made, but that is all we know.
+
Now, the question arises: what value does <code>$counter</code> have to start with? We know that it increases by one every time a copy is made, but that is all we know.
  
 
This value needs to be ''initialized'' to a certain value.
 
This value needs to be ''initialized'' to a certain value.
  
Initializing values is generally done by what is called a ''constructor''. A constructor does just that - it constructs the object. In PHP4, constructors were functions that always had the same name as the class. In PHP5, constructors are functions with the name &lt;code>__construct&lt;/code>. We will use &lt;code>__construct&lt;/code> here.
+
Initializing values is generally done by what is called a ''constructor''. A constructor does just that - it constructs the object. In PHP5, constructors are functions with the name <code>__construct</code>. We will use <code>__construct</code> here.
  
 
So our class now becomes:
 
So our class now becomes:
&lt;source lang="php">
+
<syntaxhighlight lang="php">
 
class CopierWithCounter extends Copier
 
class CopierWithCounter extends Copier
 
{
 
{
     var $counter;
+
     public $counter;
  
     function __construct() {
+
     public function __construct() {
 
         $this->counter = 0;
 
         $this->counter = 0;
 
     }
 
     }
  
     function copy() {
+
     public function copy() {
 
         $this->counter++;
 
         $this->counter++;
 
         parent::copy();
 
         parent::copy();
 
     }
 
     }
 
}
 
}
&lt;/source>
+
</syntaxhighlight>
  
 
Now suppose we wanted to create an even more advanced copier. We can do that by creating another child class. Let's create a copier that is able to do multiple copies. In order to do this, we need a way to specify how many copies we want and a way to remember this number. We will add a method called 'setCopies()':
 
Now suppose we wanted to create an even more advanced copier. We can do that by creating another child class. Let's create a copier that is able to do multiple copies. In order to do this, we need a way to specify how many copies we want and a way to remember this number. We will add a method called 'setCopies()':
  
&lt;source lang="php">
+
<syntaxhighlight lang="php">
 
class CopierMultipleCopies extends CopierWithCounter
 
class CopierMultipleCopies extends CopierWithCounter
 
{
 
{
     var $copies;
+
     public $copies;
  
     function setCopies( $copies ) {
+
     public function setCopies( $copies ) {
 
         $this->copies = $copies;
 
         $this->copies = $copies;
 
     }
 
     }
 
}
 
}
&lt;/source>
+
</syntaxhighlight>
 
We now have a way to specify how many copies we want to make.
 
We now have a way to specify how many copies we want to make.
  
Now, it is appropriate here to say a word about ''scope''. When we talk about scope, we talk about where a certain variable can be seen. You will notice that in our class, we have a property called &lt;code>$copies&lt;/code>. But we also have a parameter called &lt;code>$copies&lt;/code> in our method &lt;code>setCopies&lt;/code>. How do you tell them apart?
+
Now, it is appropriate here to say a word about ''scope''. When we talk about scope, we talk about where a certain variable can be seen. You will notice that in our class, we have a property called <code>$copies</code>. But we also have a parameter called <code>$copies</code> in our method <code>setCopies</code>. How do you tell them apart?
  
Well, the rules of scope tell us which variable we are talking about. If a method takes a parameter, say &lt;code>$copies&lt;/code> (as above), then if I use &lt;code>$copies&lt;/code> inside that method, I am referring to <span class="plainlinks">[http://www.thepiggybackrider.com/ <span style="color:black;font-weight:normal; text-decoration:none!important; background:none!important; text-decoration:none;/*CITATION*/">kid carrier</span>]</span> that parameter. There may be other variables called &lt;code>$copies&lt;/code> that are defined in other places, but I don't care about those - I only care about the one inside of my function. If I want to refer to a property of the current object, I use the &lt;code>$this&lt;/code> keyword. So, if I use &lt;code>$this->copies&lt;/code>, then I am talking about the &lt;code>$copies&lt;/code> property that belongs to my current object.
+
Well, the rules of scope tell us which variable we are talking about. If a method takes a parameter, say <code>$copies</code> (as above), then if I use <code>$copies</code> inside that method, I am referring to that parameter. There may be other variables called <code>$copies</code> that are defined in other places, but I don't care about those - I only care about the one inside of my function. If I want to refer to a property of the current object, I use the <code>$this</code> keyword. So, if I use <code>$this->copies</code>, then I am talking about the <code>$copies</code> property that belongs to my current object.
  
So that aside, our &lt;code>setCopies()&lt;/code> method will allow us to set the number of copies that we want to make using our copier. The method takes one parameter - &lt;code>$copies&lt;/code>, and stores it in the object.
+
So that aside, our <code>setCopies()</code> method will allow us to set the number of copies that we want to make using our copier. The method takes one parameter - <code>$copies</code>, and stores it in the object.
  
You will notice that our current class definition for CopierMultipleCopies doesn't define a &lt;code>copy()&lt;/code> method or a constructor. But, because it extends CopierWithCounter, it inherits the &lt;code>copy()&lt;/code> method from CopierWithCounter, and also inherits the properties. So, without doing any extra work, we already have a Copier with a counter.
+
You will notice that our current class definition for CopierMultipleCopies doesn't define a <code>copy()</code> method or a constructor. But, because it extends CopierWithCounter, it inherits the <code>copy()</code> method from CopierWithCounter, and also inherits the properties. So, without doing any extra work, we already have a Copier with a counter.
  
But we still want to extend the functionality of the &lt;code>copy()&lt;code> method so that it actually makes the multiple copies. So, we add a method definition to our class. We will also add a constructor that will add the functionality of initializing the number of copies to 1.
+
But we still want to extend the functionality of the <code>copy()</code> method so that it actually makes the multiple copies. So, we add a method definition to our class. We will also add a constructor that will add the functionality of initializing the number of copies to 1.
  
&lt;source lang="php">
+
<syntaxhighlight lang="php">
 
class CopierMultipleCopies extends CopierWithCounter
 
class CopierMultipleCopies extends CopierWithCounter
 
{
 
{
     var $copies;
+
     public $copies;
  
     function __construct() {
+
     public function __construct() {
 
         $this->copies = 1;
 
         $this->copies = 1;
 
         parent::__construct();
 
         parent::__construct();
 
     }
 
     }
  
     function setCopies( $copies ) {
+
     public function setCopies( $copies ) {
 
         $this->copies = $copies;
 
         $this->copies = $copies;
 
     }
 
     }
  
     function copy() {
+
     public function copy() {
         for ($i = 0; $i &lt; $this->copies; $i++) {
+
         for ($i = 0; $i < $this->copies; $i++) {
 
             parent::copy();
 
             parent::copy();
 
         }
 
         }
 
     }
 
     }
 
}
 
}
&lt;/source>
+
</syntaxhighlight>
  
So what have we done here? Well, first, in our constructor we initialized the $copies variable to 1. Thus, if we don't tell our copier otherwise, it will make one copy when the &lt;code>copy()&lt;/code> method is invoked. Note that we don't have to rewrite the code to initialize the counter - we just call &lt;code>parent::__construct()&lt;/code> and our parent constructor will handle that.
+
So what have we done here? Well, first, in our constructor we initialized the $copies variable to 1. Thus, if we don't tell our copier otherwise, it will make one copy when the <code>copy()</code> method is invoked. Note that we don't have to rewrite the code to initialize the counter - we just call <code>parent::__construct()</code> and our parent constructor will handle that.
  
Then, we ''overrode'' the &lt;code>copy()&lt;/code> method. Inside of our &lt;code>copy()&lt;/code> method we have what is called a ''[[http://en.wikipedia.org/wiki/For_loop|for loop]]''.   
+
Then, we ''overrode'' the <code>copy()</code> method. Inside of our <code>copy()</code> method we have what is called a ''[[http://en.wikipedia.org/wiki/For_loop|for loop]]''.   
  
 
In the first line of the for loop, you will see three parts divided by semicolons.   
 
In the first line of the for loop, you will see three parts divided by semicolons.   
Line 210: Line 210:
  
 
So that is our copier. Now to use our copier, we can add something like this to our code:
 
So that is our copier. Now to use our copier, we can add something like this to our code:
&lt;source lang="php">
+
<syntaxhighlight lang="php">
 
$copier = new CopierMultipleCopies();
 
$copier = new CopierMultipleCopies();
 
$copier->copy();
 
$copier->copy();
Line 216: Line 216:
 
$copier->setCopies( 10 );
 
$copier->setCopies( 10 );
 
$copier->copy();
 
$copier->copy();
&lt;/source>
+
</syntaxhighlight>
  
 
So notice a couple of things:
 
So notice a couple of things:
Line 228: Line 228:
 
The advanced copiers added more features, but this was separate from the original interface. (just as a car with cruise control has the same basic interface as a car without cruise control, but to take advantage of the cruise control you need to know how to set it).   
 
The advanced copiers added more features, but this was separate from the original interface. (just as a car with cruise control has the same basic interface as a car without cruise control, but to take advantage of the cruise control you need to know how to set it).   
  
This idea is an important part of the design of Joomla!.
+
Object Oriented Programming is an important part of the design of Joomla!.
  
 
''**ianmac** put together this OOPs overview for the community; [http://forum.joomla.org/index.php/topic,200185.msg943596.html#msg943596 Post #1] and [http://forum.joomla.org/index.php/topic,200694.msg944114.html#msg944114 Post #2]''
 
''**ianmac** put together this OOPs overview for the community; [http://forum.joomla.org/index.php/topic,200185.msg943596.html#msg943596 Post #1] and [http://forum.joomla.org/index.php/topic,200694.msg944114.html#msg944114 Post #2]''
  
 +
== See Also ==
 +
[http://us3.php.net/manual/en/oop5.intro.php Introduction to PHP 5 OOP]
 +
 +
<noinclude>
 
[[Category:Development]]
 
[[Category:Development]]
 +
[[Category:Component Development]]
 +
[[Category:Beginner Development]]
 +
[[Category:Development Recommended Reading]]
 
[[Category:Tutorials]]
 
[[Category:Tutorials]]
 +
</noinclude>

Revision as of 17:40, 7 July 2015

PHP is an object oriented language, and to use the MVC structure as implemented by Joomla!, a solid understanding of object oriented programming (OOP) is required. This document explains the reasons for using objects and the way objects are used in PHP and Joomla.

Introduction to Objects[edit]

As we venture into object oriented programming, it is important to note that it is called 'object' oriented for a reason.

Before object oriented programming (OOP), everything was based on functions and variables. Let's consider an application that calculates a person's BMI. You might have three variables: $height and $weight and $name. These variables would be used to store a person's name, height and weight. You might then have a function called calculateBMI(), which would accept as parameters $height and $weight.

This would look something like:

public function calculateBMI( $height, $weight ) {
    return $weight / $height;
}

But it is very easy to lose track of all these variables in the code, not to mention the fact that only one person is supported at a time. The idea behind objects is to encapsulate this data and the functions to manipulate it into one package. The definition of this package is called a class.

So we might have:

class person
{
    public $name;
    public $height;
    public $weight;

    public function getBMI() {
        return $this->weight / $this->height;
    }
}

Then, if you want to create an object which represents a person, you would do:

$person = new person();

This is called instantiating the class, because it creates an instance of the class (an object described by the class).

Now, you can modify the variables (which are called properties), using:

$person->height = 2;
$person->weight = 50;

Then you can invoke its functions (which are called methods) using:

$bmi = $person->getBMI();

Often, many classes are similar, but too different to put into one class. For example, all animals have lungs, and because humans and cats are animals, they could both have a $lung_capacity. However, cats have tails, so should an Animal class have a $tail_length? No, that is not necessary. You can make a class a subclass or child class of another, essentially stating that the subclass has everything its parent class has, plus some extensions.

In Joomla, most classes are children of JObject. Now, if we were to make person a child class of JObject, then we would inherit the capabilities of the JObject class. We would then change the definition to something like:

class person extends JObject
{
    public $name;
    public $height;
    public $weight;

    public function getBMI() {
        return $this->weight / $this->height;
    }
}

Then we could manipulate our person using the get() and set() methods that JObject has:

$person->set( 'name', 'Bob' );
$person->set( 'height', 2 );
$person->set( 'weight', 50 );
$person->get( 'weight' );
echo $person->getBMI();

You will notice the use of $this inside classes a lot. $this is a reference to the current object. So if I am inside a class, and I use say $this->height = 2;, then that means I am setting the property 'height' of the current object to 2. When we use $this->height, we aren't talking about any height, but we're talking about the current object height.

More on Objects[edit]

As I said, Objects are called Objects for a reason. If you have a real life object, say a photocopier, there is an external interface (say, a paper tray, the copier glass, the keypad, etc.). Objects in OOP are designed to approximate that setup.

So, I might have a class called copier. Now, what operations do I generally need to do with a copier? Well, the basic functionality I need is copy functionality. So I need a method called 'copy':

class Copier
{
    public function copy() {
        echo 'One copy made';
    }
}

Now, this is a very basic copier. What if I wanted to extend the functionality of my Copier? Well, to extend the functionality, I create a child class. A child class will inherit all the functionality of the parent class.

Let's suppose we wanted to create a copier that would keep track of the number of copies it had made. So, we would need to add a property which would keep track of this number, and then we need to somehow adjust this number each time we make a copy.

So here is our child class:

class CopierWithCounter extends Copier
{
    public $counter;

    public function copy() {
        $this->counter++;
        parent::copy();
    }
}

So we now have a property called $counter that keeps track of the number of copies made. Notice that the method we defined has the same name as the method in the Copier class. What this means is that we don't need to learn anything new to use the copier - it behaves in the same way as our old copier, but it just keep track of the number of copies.

You will see that inside of the copy() method there is a line: parent::copy(). The parent keyword references the parent class, which is in this case Copier. So this line will invoke the copy() method of the Copier class. In this way, we don't have to rewrite the functionality to make a copy - we have already done that in the Copier class.

So we have the exact same functionality as the Copier class, except that anytime a copy is made it will increment the $copies property by 1. Just as in real life, the addition of the counter doesn't change the way that I use the copier - I don't need to know anything about the counter to just make a simple copy.

Now, the question arises: what value does $counter have to start with? We know that it increases by one every time a copy is made, but that is all we know.

This value needs to be initialized to a certain value.

Initializing values is generally done by what is called a constructor. A constructor does just that - it constructs the object. In PHP5, constructors are functions with the name __construct. We will use __construct here.

So our class now becomes:

class CopierWithCounter extends Copier
{
    public $counter;

    public function __construct() {
        $this->counter = 0;
    }

    public function copy() {
        $this->counter++;
        parent::copy();
    }
}

Now suppose we wanted to create an even more advanced copier. We can do that by creating another child class. Let's create a copier that is able to do multiple copies. In order to do this, we need a way to specify how many copies we want and a way to remember this number. We will add a method called 'setCopies()':

class CopierMultipleCopies extends CopierWithCounter
{
    public $copies;

    public function setCopies( $copies ) {
        $this->copies = $copies;
    }
}

We now have a way to specify how many copies we want to make.

Now, it is appropriate here to say a word about scope. When we talk about scope, we talk about where a certain variable can be seen. You will notice that in our class, we have a property called $copies. But we also have a parameter called $copies in our method setCopies. How do you tell them apart?

Well, the rules of scope tell us which variable we are talking about. If a method takes a parameter, say $copies (as above), then if I use $copies inside that method, I am referring to that parameter. There may be other variables called $copies that are defined in other places, but I don't care about those - I only care about the one inside of my function. If I want to refer to a property of the current object, I use the $this keyword. So, if I use $this->copies, then I am talking about the $copies property that belongs to my current object.

So that aside, our setCopies() method will allow us to set the number of copies that we want to make using our copier. The method takes one parameter - $copies, and stores it in the object.

You will notice that our current class definition for CopierMultipleCopies doesn't define a copy() method or a constructor. But, because it extends CopierWithCounter, it inherits the copy() method from CopierWithCounter, and also inherits the properties. So, without doing any extra work, we already have a Copier with a counter.

But we still want to extend the functionality of the copy() method so that it actually makes the multiple copies. So, we add a method definition to our class. We will also add a constructor that will add the functionality of initializing the number of copies to 1.

class CopierMultipleCopies extends CopierWithCounter
{
    public $copies;

    public function __construct() {
        $this->copies = 1;
        parent::__construct();
    }

    public function setCopies( $copies ) {
        $this->copies = $copies;
    }

    public function copy() {
        for ($i = 0; $i < $this->copies; $i++) {
            parent::copy();
        }
    }
}

So what have we done here? Well, first, in our constructor we initialized the $copies variable to 1. Thus, if we don't tell our copier otherwise, it will make one copy when the copy() method is invoked. Note that we don't have to rewrite the code to initialize the counter - we just call parent::__construct() and our parent constructor will handle that.

Then, we overrode the copy() method. Inside of our copy() method we have what is called a [loop].

In the first line of the for loop, you will see three parts divided by semicolons.

The first part is the initialization. We will use $i as a counter variable, and we will start it at 0. $i will essentially keep track of the number of copies we have made out of the total number that we have to do.

The second part is the condition. At the beginning of each run of the for loop, this condition is checked to determine if it is true or not. If the condition is true, we execute the stuff inside of the braces. If it is not, then we are done the loop.

The last part is the incrementor. This is code that gets executed after every pass through the loop.

So it will run something like:

  • take our variable i and set it to 0.
  • Check if our variable i is less than the number of copies that we have to make
  • if it is, then we will make a copy
  • we will increment i by 1 and go back to step 2

You can have much more complex for loops than this, but this is the basic idea.

So that is our copier. Now to use our copier, we can add something like this to our code:

$copier = new CopierMultipleCopies();
$copier->copy();
$copier->copy();
$copier->setCopies( 10 );
$copier->copy();

So notice a couple of things:

First, as we made our copier more and more complex, we didn't have to duplicate code. That is, in our most complex copier, we didn't have to worry about creating code to make the actual copy. We just used the method that came with our original copier. Also, in our final copier we didn't have to re-implement the counter - we again just used the method that had already been defined to do this.

Second, our new copier can serve as a drop in replacement for our old copier. Yes, each copier was more advanced than the previous one, but it was still possible with the most advanced one to just create it and invoke the copy() method, and it would create a copy.

If I want to use the more advanced functionality, such as reading the counter or changing the number of copies to be made, I need to know about these features, but I can still ignorantly use the copier as if it was the original Copier. (i.e. the original Copier class had a certain interface that was standard.)

The advanced copiers added more features, but this was separate from the original interface. (just as a car with cruise control has the same basic interface as a car without cruise control, but to take advantage of the cruise control you need to know how to set it).

Object Oriented Programming is an important part of the design of Joomla!.

**ianmac** put together this OOPs overview for the community; Post #1 and Post #2

See Also[edit]

Introduction to PHP 5 OOP