There are a number of special keywords you can place before a class, a class function definition, or a class variable to alter the way PHP works with it - here's the full list, along with what each of them does:
Public: This variable or function can be used from anywhere in the script
Private: This variable or function can only be used by the object it is part of; it cannot be accessed elsewhere
Protected: This variable or function can only be used by the object it is part of, or descendents of that class
Final: This variable or function cannot be overridden in inherited classes
Abstract: This function or class cannot be used directly - you must inherit from them first
That is just a vague description of what each of them do - to make sure you fully understand each of them, here are examples:
Public
Public variables and functions are accessible from anywhere in your script, which makes this modifier the easiest to use. In PHP 4, all object variables were declared with "var" and were essentially public, but using this terminology is deprecated and may generate compiler warnings. Take a look at this following code:
<?php
class dog {
public $Name;
public function bark() {
print "Woof!\n";
}
}
class poodle extends dog {
public function bark() {
print "Yip!\n";
}
}
$poppy = new poodle;
$poppy->Name = "Poppy";
print $poppy->Name;?>
If you try that code out, you will see it works in precisely the same way as before - the public keyword does not make any difference. The reason behind is that, by default, all class functions are public, because before PHP 5 there was no way to make them anything else.
While the public keyword is not needed, I recommend you use it anyway - it is a good way to remind people who read your code that a given function is indeed public, and also it is possible that class functions without an access modifier may be deprecated in the future.
When you use public for variables, it is needed - you always need to specify an access modifier for variables, because otherwise there'd be no way to define what variables a class has. Previous versions of PHP used the "var" keyword to declare class variables, again because it had no concept of access modifiers - you should avoid this, and be more specific with public or one of the other keywords.
=====================
Private
The problem with public variables is that they allow functions to be called and variables to set from anywhere within your script, which is generally not a smart thing. Think back to before - we had a dogtag object $DogTag inside each dog object as well as a$Name variable, but they had repeated information inside.
If we had changed the $Name variable, would $DogTag have been updated automatically? Of course not - it would have remained the same, which was different to the new $Name value:
$poppy = new poodle;$poppy->Name = "Poppy";$poppy->DogTag = new dogtag;$poppy->DogTag->Words = "My name is Poppy. If you find me, please call 555-1234";$poppy->Name = "Penny";
print $poppy->DogTag->Words;
If you try that, you will see the problem. This has arisen because we have allowed any part of our script to directly access the internals of our dog objects. Here is one solution:
class dog {
public $Name;
public $DogTag;
public function setName($NewName) {
$Name = $NewName;
$DogTag->Words = "My name is $NewName. If you find me, please call 555-1234";
}
This time the dog object has embedded logic in that knows how to handle a renaming properly. As long as people use thesetName() function, the dog's name and its dog tag will get updated with just one call.
Given the above script, however, it is still possible for some unscrupulous, lazy, or ignorant programmer to write $poppy->Name = "Rover", thereby not using the special setName() function we've provided. This is where private variables come in - we can instruct PHP that the variable $Name is private, and can therefore only be changed with the class its part of. Here is the new code:
class dog {
private $Name;
private $DogTag;
public function setName($NewName) {
Note that both $Name and $DogTag are private, which means no one can access them unless doing so in a function that is part of the object, such as setName(). Note that setName() itself remains public - we want this to be accessible by anyone.
Now if our lazy programmer comes along and tries to set $Name directly using code like $poppy->Name, they will not get what they were expecting. You see, if they try to alter a private variable directly PHP will automatically spit out an error message. However, if that private variable was inherited from another class, PHP will try to accommodate their request by having a private variable and a public variable. Yes, this is somewhat confusing, however the following code should clear things up:
<?php
class dog {
private $Name;
}
class poodle extends dog { }
$poppy = new poodle;
$poppy->Name = "Poppy";
print_r($poppy);?>
Running that script will output the following:
poodle Object
(
[Name:private] =>
[Name] => Poppy
)
Notice that there are two Name variables - one that is private and cannot be touched, and another that PHP creates for local use as requested. Clearly this is confusing, and you should try to avoid this situation if possible.
Note that private functions and variables can only be accessed by the exact class that owns them - child classes cannot access private parent functions variables. To do this, you need the protected keyword instead.
======================
Protected
Variables and functions marked as protected are accessible only through the object that owns them, whether or not they are declared in that object's class or whether they have descended from a parent class. Consider the following code:
<?php
class dog {
public $Name;
private function getName() {
return $this->Name;
}
}
class poodle extends dog {
public function bark() {
print "'Woof', says " . $this->getName();
}
}
$poppy = new poodle;
$poppy->Name = "Poppy";
$poppy->bark();?>
In that code, the class poodle extends from class dog, class dog has a public variable $Name and a private function getName(), and class poodle has a public function called bark(). So, we create a poodle, give it a $Name value of "Poppy" (the $Name variable comes from the dog class), then ask it to bark(). The bark() function is public, which means we can call it as shown above, so this is all well and good.
However, note that the bark() function calls the getName() function, which is part of the dog class and was marked private - this will stop the script from working, because private variables and functions cannot be accessed from inherited classes. That is, we cannot access private dog functions and variables from inside the poodle class.
Now try changing bark() to protected, and all should become clear - the variable is still not available to the world as a whole, but handles inheritance as you would expect, which means that we can access getName() from inside poodle.
========================
Final
The final keyword is used to declare that a function or class cannot be overriden by a sub-class. This is another way of stopping other programmers using your code outside the bounds you had planned for it.
Take a look at the following code:
class dog {
private $Name;
private $DogTag;
final public function bark() {
print "Woof!\n";
}
The dog bark() function is now declared as being final, which means it cannot be overridden in a child class. If we have bark()redefined in the poodle class, PHP outputs a fatal error message: Cannot override final method dog::bark(). Using the final keyword is entirely optional, but it makes your life easier by acting as a safeguard against people overriding a function you believe should be permanent.
For stronger protection, the final keyword can also be used to declare a class as uninheritable - that is, that programmers cannot extend another class from it. Take a look at this script:
<?php
final class dog {
public $Name;
private function getName() {
return $this->Name;
}
}
class poodle extends dog {
public function bark() {
print "'Woof', says " . $this->getName();
}
}?>
Attempting to run that script will result in a fatal error, with the message "Class poodle may not inherit from final class (dog)".
===========================
Abstract
The abstract keyword is used to say that a function or class cannot be created in your program as it stands. This might not make sense at first - after all, why bother defining a class then saying no one can use it?
Well, it is helpful because it does not stop people inheriting from that abstract class to create a new, non-abstract (concrete) class.
Consider this code:
$poppy = new dog;
The code is perfectly legal - we have a class "dog", and we're creating one instance of that and assigning it to $poppy. However, given that we have actual breeds of dog to choose from, what this code actually means is "create a dog with no particular breed". Have you ever seen a dog with no breed? Thought not - even mongrels have breed classifications, which means that a dog without a breed is impossible and should not be allowed.
We can use the abstract keyword to back this up. Here is some code:
abstract class dog {
private $Name;// etc
$poppy = new dog;
The dog class is now abstract, and $poppy is now being created as an abstract dog object. The result? PHP halts execution with a fatal error, "Cannot instantiate abstract class dog".
As mentioned already, you can also use the abstract keyword with functions, but if a class has at least one abstract function the class itself must be declared abstract. Also, you will get errors if you try to provide any code inside an abstract function, which makes this illegal:
abstract class dog {
abstract function bark() {
print "Woof!";
}
}
It even makes this illegal...
abstract class dog {
abstract function bark() { }
}
Instead, a proper abstract function should look like this:
abstract class dog {
abstract function bark();
}
Author's Note: If it helps you understand things better, you can think of abstract classes as being quite like interfaces, which are discussed shortly.
No comments:
Post a Comment