Public, private, or protected?

The developers of PHP were actually taken a bit by surprise when object-oriented programming caught on the way it did within the PHP community. Objects were added as an afterthought to PHP 3, and were little more than syntactic sugar for associative arrays. PHP 4 brought some advancements in object support, but with PHP 5, the language has finally graduated into a completely respectable object-oriented language.

Among the features that you expect to find in object-oriented languages is the ability to limit access to your objects’ methods and properties. The goal here is to avoid letting your scripts get into trouble by messing with things they don’t need access to.

As a for instance, suppose you have an object that’s responsible for handling your database transactions. And on this object there exists a property called ‘dbConnect’ whose purpose is to contain the resource that will let PHP run queries on a database. And you’ve done a great job putting together a class that will execute SQL queries, handle transactions, do updates, and really is just an all around beautiful piece of code. And you’d like to ensure that this dbConnect property, one that your class sets up in the constructor and then makes use of in a few key functions, only ever has the value you expect it to.

But in PHP 4, you would just have to write strongly-worded comments and hope that none of the people on your project would be foolish enough to try and get the dbConnect property directly, thereby completely by-passing your class’s way of doing things securely and efficiently. Or worse yet, have a script go in and directly modify the value of dbConnect. After all, you don’t want dbConnect to change unless the database name, host, user, or password were changed too. If an outside script modifies it directly, your object may not actually be running commands on the database it thinks its running commands on, and that might lead to a whole cascade of errors.

So to deal with this type of situation, PHP 5 says you can now specify that a class has certain methods or properties that can only be accessed by the class itself. All you have to do is put the keyword ‘private’ in front of the declaration.

As a convention, I recommend you put an underscore in front of your private or protected properties and methods. It’s a nice way to know, at a glance, whether you’re dealing with something that’s public or not. It’s a pretty common convention. I don’t know where it started, but it’s one I’m quick to endorse. {show example class definition}

Now, the obvious question you’re probably asking, is what’s the difference between private and protected? Well, neither one can be invoked by an outside script, but while private methods and properties can only be invoked by the classes that declared them, protected properties and methods can also be invoked by the children of the classes that declared them.

So, if _protectedMethod is a protected method on the class ParentClass, and ParentClass is extended by a class called ‘ChildClass’, then an object of type ‘ChildClass’ would be allowed to invoke $this->_protectedSpecial(). {show example}

On the other hand, ParentClass also defines ‘_privateMethod’ as a private method. If a ChildClass object tries to invoke $this->_privateMethod() it will trigger a fatal error. {uncomment call to _privateMethod and then show example triggering error}

However, while this is probably the most common way of accessing a protected property or method from a child class, it doesn’t have to be in the context of “$this” in order to work. Consider this next example: {show example method}

$parent = new ParentClass();
$parent->_protectedMethod();

Then in the context of being on ChildClass somewhere, this code will execute without an error. {show output from method accessing protected property and method this way}

{while explaining next P, show method declaration with no scope keyword, access it in public context, then go back and put keyword ‘public’ in front of it}

As for public, that’s technically the default for your methods. In PHP 4, all properties and methods were public, meaning they could be accessed or updated in any context. When you define a method, if you just write function <methodName>([<argsList>]) {… } with nothing in front of it, it’s public. See? {show output} However, in order to have my methods look consistent, I like to place the keyword “public” in front of my public methods. {return to declaration and write ‘public’} To me, it actually looks weird to see a method declaration without one of ‘public’, ‘private’, or ‘protected’ in front of it.

As for properties, they work the same way. To declare a property public private or protected, just put the desired keyword in front of its declaration. In PHP 4, properties were always preceded with the ‘var’ keyword. To preserve backwards-compatibility, this does actually still work. It just creates a new public property. However, since this technique is deprecated, you should avoid it.

The last keyword I want to talk about in this video is, no pun intended, “final”. The final keyword is used to prevent methods from being overwritten by child classes, or to prevent a class from being extended entirely. If a child class tried to re-declare a parent class’s final method, PHP would trigger a fatal error as soon as the file containing the child class got included.

I’ll show you:

{open ParentClass class file and place ‘final’ in front of a method declaration}

Since ChildClass also defines the ‘doSomething’ method, PHP is going to complain about it:

{show output with fatal error}

This is a great tool for situations where you know that, if a child class writes its own method that your parent class has already declared, then there’s a good chance that it’ll break your functionality. Just make that property or method final and you won’t have to worry about it.

The other way you can use final is by placing it in front of a class name in the declaration. This will prevent any class from extending it. And you can see that here: {place ‘final’ in front of ‘class ParentClass’}

{show output with fatal error}

That’s all for this video.

January 22 2010 09:42 am | Schmategories

Comments are closed.