The question you raise Shears is a good one. There isn't a definitive answer. It all depends on how much encapsulation you want.
No encapsulation, widely accepted to be a bad thing 99% of the time:
Light encapsulation:
Code: Select all
class Foo
{
protected $_a;
public function getA()
{
return $this->_a;
}
public function setA($newA)
{
$this->_a = $newA;
}
}
Although this is light encapsulation this gives you complete protection from the outside via the interface. For instance you can add a type hint or throw an exception in setA() to control what goes in. At the same time you still have the flexibility to use the property for anything you please inside the class and using the property directly is faster, easier to read and less typing. Most of the time this is what you want.
The next level of encapsulation up is the same as above only with $_a is set as private. Lots of people miss this level of encapsulation out as the difference is often small and the implication of inheritance is an "is a" relationship. The theory is if Foo is Foo then something that extends Foo is going to be Foo. Why should there be any difference with how we treat the data access in Foo with something else that is also Foo? I can appreciate this point of view but the implication of it is that will never use public nor private and so every property you ever declare is going to be protected... and formation of a habit begins. No longer are you going to consider what strength of visibility you need, you're just going to go with protected. Now this might sound great at first, less thought required, Pythonists might agree with you but on the other side of the hedge in the Ruby camp we're going to disagree. We think it's worth evaluating which is best even if it takes a little longer and consistency isn't the be all and end all of programming.
So it's worth thinking now. What really is the point in private? It does have a purpose and it is particularly useful in flex points. If you are writing a good library you will no doubt provide many flex points. Places where code can be extended, in order to change or augment it's purpose. Privates are really useful here. You want to prevent extenders from abusing the library and privates can be used to control this. Personally I have developed an anti-habit habit. I declare all my properties as private and change them to protected if I find it necessary later. I find that only roughly 50% of the time is it necessary to do so. Additionally (and this is good practise for interface level encapsulation also) the second a subclass needs access to it. First I ask myself - "Is the task I need to perform with this private in this subclass really the responsibility of the subclass? Should the super provide a method for doing it instead?" if the answer to the latter is yes then I can provide that method, for the benefit of the subclass, and retain my encapsulation.
Other ways you can improve your encapsulation:
- Use a parametrized constructor to make it possible to only assign a value once.
- If you have many properties not being used by several of your methods you may be able to put those properties and the methods that are using them into a second class. This is called the extract class refactor and will provide you with an additional level of encapsulation and also makes it possible to change the two sets of functionality separately. Unfortunately it also incurs the considerations of how those objects will interact and how they will be introduced to each (how instantiation will be managed). So it's a trade-off. Generally I only do it if I know I'm going to benefit from the increased polymorphism as well.
The next question you may be asking yourself is "How do I know how much encapsulation I need?". That's another post and another night, for it is late here.