I have read and heard from a few people that say to never use the private access modifier, and instead always use protected. They say this is because you never know who will be extending your class, etc.
What do you guys think?
| SitePoint Sponsor |
I have read and heard from a few people that say to never use the private access modifier, and instead always use protected. They say this is because you never know who will be extending your class, etc.
What do you guys think?

Most of the fields that a class uses for its internal processing should not be required to be accessible from any classes derived from that one. The more you can specify as private the easier it will be to maintain the code as there are fewer places where the field can be referenced. You can always shift a field from private to protected later if you need to and the move will have no impact on the code already written.
Stephen J Chapman
javascriptexample.net, Book Reviews, follow me on Twitter
HTML Help, CSS Help, JavaScript Help, PHP/mySQL Help, blog
<input name="html5" type="text" required pattern="^$">
I use protected by default. Then again, I tend to minimise use of inheritance, as much as possible, making the choice somewhat obsolete. The problem I have with private, is that it works on the class level. public and protected works on the object instance level. The latter, I can find use for, but the former promotes a way of thinking, which I'm not comfortable with.
If you want to have something unchanged when your class is used use private, in all the other cases use protected or public.
Yep, I know how the modifiers work.
The way I see it though is if you declare a method/member private you are essentially saying, "I know every single way that my class will be implemented in the future, and I know for certain that no one will ever need to use this method/member". Of course, we can never know this for sure, as future developers may find a need to call this method, or extend it, right?

There is nothing to stop you updating the class in the future to move something from private to protected if it turns out you need it that way. Just a minor change to an existing class that would have no impact whatsoever on anything currently using it.
Stephen J Chapman
javascriptexample.net, Book Reviews, follow me on Twitter
HTML Help, CSS Help, JavaScript Help, PHP/mySQL Help, blog
<input name="html5" type="text" required pattern="^$">



Not necessarily. If a derived class tries to access a private variable then __get() will get kicked off. The __get() implementation might then return some particular value. If the ancestor variable is then changed from private to protected then __get will no longer be called.
PHP Code:class Base
{
private $shy = 27;
}
class Extend extends Base
{
function __get($name) {
if ($name == 'shy') return 42;
}
function run()
{
echo "Shy {$this->shy}\n";
}
}


Providing public or protected access to member variables / methods implies that those elements will not change in form or function. Because changing them will likely impact the client code that accesses them. For closed projects where have access to both the class and the client code, changing an accessible variable / method might not seem like a big deal but it depends on how much code needs to be changed. For cases where I'm providing a library to others outside my team, I need to be careful about changing public and protected member variables / methods.
Just my $0.02 worth....
mikem

In my own framework all of the classes have the extender _prototype on their names in my core app code. For example
class PAMWF_Class_prototype {}
Then if I need to modify the class in a specific project for a client I simply use
class PAMWF_Class extends PAMWF_Class_prototype{}
The magic happens in the __autoload function. After it finds a class' file it looks for an override. If it finds it it loads both. Otherwise it wraps the prototype using an eval statement
eval('class PAMWF_Class extends PAMWF_Class_prototype{}');
This techinique completly precludes the use of private - I never use it since I don't know when I'll want to customize a block of code for a site.
It also has the annoying trait of breaking the ability of Zen Studio to follow class relationships, so the code completion features don't work![]()




If a company has 20 programmers, only 4 of them have write access to core classes, and you are not one of them, how are they going to extend it?
Usually, in big companies, you can only checkout core components. If one of the core developers assumed that no one will ever need to extend that class, he is either psychic or human (we all make mistakes).





I strongly agree. You should always be able to extend a class in any way you see fit. Final and private are a complete no-no in my book. If you feel the need to protect bits within a class that's probably a smell indicating that something ought to be split off into a separate class.
I'd go even further though: don't use any of them and instead stick with the underscores we used in php4. Clearly labelling the public interface is important. Enforcing it is not. All they do is add clutter.
working on: Aperiplus, Rephactor, Phemto
useful links: xUnit test patterns, martinfowler.com, c2 wiki
Yep, which is similar to a situation I am encountering at work. There is a class that I want to basically add some functionality and members to, so that it is basically a "smarter" class.
However, most of the stuff is declared as Private (I guess the original programmer felt there would never be a need to upgrade it) and I do not have write access to the base class. What can I do? Since I cannot inherit from it and add extra functionality, I am forced to basically duplicate the class and all its members/methods or use aggregation.

...but then maintenance becomes a huge pain. If you are working with an external library, you do not want to go around and change "private" to "protected" every time you upgrade the library. This is one thing that is a minor annoyance about the Zend Framework: everything is either public or private, making inheritance quite useless.
Another school of thought is that most protected / private methods should be in a different class. Look at your code and I bet most of your private methods should really be in a separate class.
If you work with an external library and you meet private, you will have to go in the core of that library and make your changes. It would be good, if you supply your changes to the initial developer, too.
This is a very wrong approach, if I need something private, that means I want it private. Otherwise, I would separate it in a different class.




[RANT]
Experience taught me that access modifiers, as currently defined in Java and therefore PHP, are the worst possible solution because they mix classes and objects, as kyber noticed earlier.
Private, in particular, is a crazy idea, because in practice the object instances are those that interact with other objects, not the classes. The problem is someone didn't realize that access control and inheritance rights are two separate problems and has tried to solve them with a single solution.
In a perfect world, we would have only one access modifier, and that is public; everything else would be by default private (or even better "internal"), meaning that only the instance itself can access its internal members. And neither would affect inheritance in any way.
[/RANT]




I never use private, but I do use protected quite a bit. I don't want to prevent someone down the road from modifying my classes or adding functionality by extending them - I sometimes don't even think final and private should exist in the language, because they eliminate most of the benefits object-oriented programming provides.
Stackbox CMS - Full edit-on-page drag-and-drop CMS
Autoridge - Vehicle information & maintenance part numbers
Twitter | Blog | Online Javascript Compressor
The sensible default is to make methods public, and data members protected. At the very least, we need those access modifiers.
Interestingly, in Ruby private is like PHP's protected; Ruby's protected is the same, but allows other objects of the same type to see the method/member. In all cases, subclasses can see the method or member. Somewhat unorthodox, but more useful IMO.

I somewhat disagree. I often see code like this:
writeToLog() is not part of the racecar and does nothing related to racing. Shouldn't that be abstracted out to a different class?PHP Code:class RaceCar
{
...
protected function writeToLog($msg)
{
file_put_contents('foo', $msg);
}
}
In my opinion, that is much cleaner code, even though it's twice as long. It also correctly delegates tasks and classifies functions.PHP Code:class Logger
{
}
class Racecar
{
protected $logger;
public function __construct(Logger $logger)
{
$this->logger = $logger;
}
}
$logger = new Logger;
$racecar = new Racecar($logger);
That sounds a bit odd too, although slightly better than the PHP way. I'm some times missing a friend access modifier. This would allow you to expose members, but only to a certain number of classes. That would be quite useful, if you use a lot of aggregation.
Ruby does another thing though, which is very nifty; It makes all properties protected, and only allows you to expose methods. This is something, which is clever to enforce at the language level. In contrast, PHP makes all properties public by default.
Dudes, learn OOP. Keyword: encapsulation. Attributes should be as private as possible and methods should be as public as possible.
You should use getters and setters, and these should be final and public (if applicable). If they require some sort of validation, then that validation should be within a separate protected method in case it is edited later, while the setter is still final.
There are rules for OOP, which are often overlooked. It's quite simple, and logical. Even more complex classes should follow this simple pattern. Of course, if your original class is bad to begin with, then there's of course nothing you can do, and you shouldn't even bother. Do it again.
PHP Code:// initial class
class MyClass {
private $name;
public function __construct($name) {
$this->setName($name);
}
final public function getName() {
return $this->name;
}
final public function setName($name) {
if ($this->isValidName($name)) {
$this->name = $name;
} else {
echo "Name was bad.\n";
}
}
protected function isValidName($name) {
return preg_match('/^[a-z]+$/i', $name);
}
}
// improved class
// we need to change isValidName() to be more restrictive about uppercase letters.
class MyImprovedClass extends MyClass {
protected function isValidName($name) {
return preg_match('/^[A-Z][a-z]+$/', $name);
}
}
$class = new MyClass("ALICE");
echo $class->getName() . "\n";
$class = new MyImprovedClass("ALICE");
echo $class->getName() . "\n";
$class = new MyImprovedClass("Alice");
echo $class->getName() . "\n";
// Outputs:
ALICE // MyClass::getName()
Name was bad. // MyImprovedClass::setName()
// MyImprovedClass::getName()
Alice // MyImprovedClass::getName()
Bookmarks