This question already has answers here:
What are public, private and protected in object oriented programming?
(7 answers)
Closed 9 years ago.
This may seem pretty simple and I am sure it is, I am just not getting it.
I understand that protected properties in a class in PHP can only be accessed within the class itself and inherited classes. Here is my code so far:
class q {
public $publicQ = "This is a public property";
protected $protectedQ = "This is a proected property";
public function displayProtected() {
echo $this->protectedQ;
}
}
$q = new q;
echo $q->publicQ; #prints "This is a public property"
echo $q->protectedQ; #nothing
$q->displayProtected();
I have read the documentation, looked at other answers on SO and the concept just is not clicking with me. What do protected properties actually do, why would we use them and why is my example not working?
Think of your public properties and methods as an API you expose to the outside world and private/protected ones as "inner workings" of your class that the outside world not only shouldn't be concerend with but shouldn't be able to mess with either.
Here comes the obligatory bad car analogy:
The methods you'd expose in a Car class could be driveForward() and driveBackwards(). Both of them would make use of a method called transmitTheDriveToTheWheels() but it shouldn't concern the car's users and shouldn't be accessed by them, so you'd "hide" it by making it private.
Your car would have an engine property. You definitely don't want someone to be able to replace the engine with a cute little kitty by going $car->engine = $kitty; so you'd make the engine private as well.
Finally, your car would have a mileage property. You want the user to be able to read the mileage but not to be able to modify it. So you make the mileage private and expose a public getMileage() method.
Now whether you want to use private or protected to encapsulate the "inner" stuff of your class, depends on whether you expect the class to be extended or not.
Protected fields can be inherited, but cannot be shown like echo $q->protectedQ;
Private fields cannot be neither displayed nor inherited.
Protected functions make your class more flexible.
Think of a class that somewhere has to load some data. It has a default implementation, which reads the data from a file. If you want to use the same class, but want to change the way it gets its data, you can create a subclass and override the getData() funciton.
You use protected/private methods to contain functionality to make your code easier to read and prevent repeating the same functionality in your public methods.
Making properties protected protects the object from being modified from outside unless you provided access via a setter.
You get more control over how your object is able to be used.
The only really difference from public methods is, as you've discovered, that protected functions can only be accessed from within the class or another class in the inheritance tree.
You wan't to declare functions as protected when they are not meant to be used from outside the class.
This is a language feature purely to make your code more understandable (easier to read) and less susceptible to bugs and misuse. There is nothing (in forms of functionality) that you can't accomplish using only public methods.
It is very useful if you're sharing your code with others or if it's some kind of library.
Specific to PHP there is a particular useful case when using PHP's magic getter and setter functions (http://www.php.net/manual/en/language.oop5.overloading.php#object.set).
public $a = '1';
protected $b = '2';
public function __get($name) {
return $this->{$name}.' (protected)';
}
$obj->a; //1
$obj->b; //2 (protected)
As per example, you can "protect" you variables and catch calls with the magic function.
It's useful if you've published a class with a variable, and you later decide to do some preprocessing internally in the class before returning the variable.
Related
I am a junior PHP programmer. I still have a lot to learn. That's why I ask this question. In a class you have a public function which you can call it from outside that class. Sometimes you have a private function which you can call several times in that class where the private function resides, for reusable purpose. I like to set the private function to static and I call that function with:
self::privateFunctionName();
By using self it reminds me that this private function resides in that class. if I use $this->privateFunctionName() for non-static function, it could be in the superclass/base class or in that subclass itself. That is why I like to use static private function. In a professional point of view, is it a good idea to use static private function instead of non-static? Is there any disadvantage that a professional programmer like you prefers to avoid the static function?
Only using self::... must not mean the method is static. parent:: and self:: work as well for non-static methods. You can find this in the PHP manual - Scope Resolution Operator (::) and I add some exemplary code excerpt at the end of the answer.
You perhaps might want to read through all answers of this earlier question:
When to use self over $this?
In total you will get there more details then my short description in this answer.
You might have been confused by the scope-resolution-operator :: which is used by those. I had a similar understanding problem grasping that.
However, do not just choose to use static methods for such a limited reason. Those static class methods should only be used in very limited and narrowed situations. As a rule of thumb:
"Do not use static class methods."
If you like to start with object oriented programming, just use normal object methods.
Here is an excerpt from existing code that shows that self:: as well as parent:: are used with standard (non-static) methods:
<?php
...
/**
* Class XMLElementIterator
*
* Iterate over XMLReader element nodes
*/
class XMLElementIterator extends XMLReaderIterator
{
private $index;
private $name;
private $didRewind;
/**
* #param XMLReader $reader
* #param null|string $name element name, leave empty or use '*' for all elements
*/
public function __construct(XMLReader $reader, $name = null)
{
parent::__construct($reader);
$this->setName($name);
}
/**
* #return void
*/
public function rewind()
{
parent::rewind();
$this->ensureCurrentElementState();
$this->didRewind = true;
$this->index = 0;
}
/**
* #return XMLReaderNode|null
*/
public function current()
{
$this->didRewind || self::rewind();
$this->ensureCurrentElementState();
return self::valid() ? new XMLReaderNode($this->reader) : null;
}
...
self:: does not in fact mean that the method is part of the same class, it may as well have been inherited from a parent class!
You should not use the semantics of static method calls to differentiate "internal" and "external" methods. There's no real point to it anyway, and you're just abusing language features for something they weren't meant for. Maybe let that be a primary lesson: don't try to invent clever new ways of using language features. Just don't.
You should view methods as small, self contained black boxes. You don't need to know and don't want to know what they do. All you know is that when you call method foo with parameter $bar, x will happen or it will return y. You don't care how this happens, just that it does because that's what the method is supposed to do.
As such, static and non-static methods convey a different use with different limitations. static methods are supposed to be called when you don't have an object, for example as alternative constructor methods (e.g. DateTime::createFromFormat).
Further, restricting a method to being static means it has no access to object instance data, which may limit you in the future. As your project evolves, you may find that your method now needs to take into account some additional data from the object to do its job. If you declared it as non-static from the beginning, all it takes is a little modification to the method itself; to the outside world it still does its job the same way (input → output). However, if you declared it as static and suddenly find yourself needing to make it non-static, you have to change a lot more code than just that one method.
Bottom line: if your method is not supposed to be exposed publicly because it's nobody's business to call it except for your own class, make it private. If the method needs to be static because it must work without object context, make it static. If it fulfils both requirements, make it private static. Otherwise, don't.
Well basically a "private static" function is a construct which is totally nonsense because it cannot be called from the outside.
There is no real difference between $this-> and using self:: expect the fact that it can be called from the outside without a object and its the same amount of work for the CPU to call the function, no matter in what namespace/class this function is located.
However the fact that a private function can only be called within the same class you always have an object and the "static" modifier is somewhat superflous here because it makes no difference.
In this cases I always like to say: do what you like its just a matter of your personal style but dont switch arround, keep it that way to develop and use the standard you feel comfortable with.
In some cases there is just "another" way and a "professional" way does not exist at all.
The trend often makes the one or the other method to become popular over time.
I have a class that when I instantiate it fill the property via construct.
The goal of this class is describe a shop, so his properties will protected because they belongs only to that class.
But the problem is that sometimes I need to get some informations about that class from the properties.
example:
class Shop {
protected $name;
protected $typology;
protected $owners;
protected $closed;
public function __construct($name,$typology,$owners,$closed)
{
$this->name = $name;
$this->typology = $typology;
$this->owners = $owners;
$this->close = $closed;
}
}
$shop = new Shop("Name Shop","vegetarian",2,1);
$superMarket = SupermarketFactory::getInstance($shop);
On the class Supermaket that (instantiated via Factory), need to get shop properties to work with.
There are a bunch of ways to make this work, but all solutions are a bit messy on my view point. I experimented this ways:
Setting getters and setters - To exclude this way, having 20 properties I need 40 methods. Scripts are not efficient.
Using __get() magic method, my IDE complain about getting those property via magic method. That's even true because at this point I could set it public.
Using Reflection, It seem to be the best of the above ways, but still need too much implementation for get only properties ( I guess)
So I would like achieve the best design to get this work, have a class that has protected property but at the same time callable in a elegant way.
There is any of design pattern that helps this goal?
I may have ask already something similar on stackOverflow but I reviewed the question and proposed in a better way.
You can define a list of properties accessible via __get() and __set() in your class docblock using the #property tag that should make them visible to IDEs
See http://www.phpdoc.org/docs/latest/for-users/phpdoc/tags/property.html and http://manual.phpdoc.org/HTMLSmartyConverter/PHP/phpDocumentor/tutorial_tags.property.pkg.html for reference and examples
PHP allows use of static member functions and variables, since 5.3 including late static bindings:
class StaticClass {
public static $staticVar;
...
}
$o = new StaticClass();
Currently, there are various options to access those static members:
$o->staticVar; // as instance variable/ function
$o::staticVar; // as class variable/ function
Other options exist for accessing members from inside the class:
self::$staticVar; // explicitly showing static usage of variable/ function
static::$staticVar; // allowing late static binding
Restructuring some existing classes that make some use of static members I've asked myself if there are best practices for working with static members in PHP?
Well, obviously, they all do different things.
$o->staticVar
This is invalid, since you cannot/should not access static properties with the instance property syntax.
StaticClass::$staticVar
This very plainly accesses a specific static variable on a very specific class.
$o::$staticVar
This accesses the static variable on the class that $o is an instance of. It's mostly used as a shorthand for the previous method and is equivalent in all respects. Obviously though, which class is used exactly depends on what class $o is an instance of.
self::$staticVar
This can be used only inside a class, and will always refer to the class that it's written in. It's a good idea to use this inside a class instead of StaticClass::$staticVar if the class refers to itself, since you don't need to worry about anything if you change the class name later. E.g.:
class Foo {
protected static $bar = 42;
public function baz() {
self::$bar; // good
Foo::$bar // the same, but should be avoided because it repeats the class name
}
}
static::$staticVar
This can also only be used inside a class and is basically the same as self above, but resolves with late static binding and may hence refer to a child class.
What the "best practice" is is debatable. I'd say you should always be as specific as necessary, but no more. $o::$staticVar and static::$staticVar both allow the class to vary through child classes, while self::$staticVar and StaticClass::$staticVar do not. Following the open/closed principle, it's a good idea to use the former, more variable method to allow for extensions.
Properties, both static and non-static, should also not be public to not break encapsulation.
Also see How Not To Kill Your Testability Using Statics.
First of all, don't use $this->staticVar. I am unsure when this changed (I believe PHP 5.4), but in recent versions it is no longer possible to retrieve static variables this way.
As for using late static binding, don't use it if you don't need it. The reason to use it would be if you plan to use inheritance and expect to change the value of the static variable in a derived class.
Can you explain what the reasoning would be on why I would want to use "protected" versus "public" or "private" on some class variables and methods in PHP5? I've just yet to find a case where I thought I needed "protected", and have either opted for "public" or "private" based on the intent. Even when working in teams, I have still yet to find a case (based on my knowledge thus far) of why "protected" is necessary for class variables and methods.
For instance, the Flourish library's fDate class provides a lot of functionality but not everything I need. So I extended w/ my own class.
I soon found out that its core internal variable, fDate::$date (time in seconds since 1970), was a private property. This made it impossible for me to access it in my subclass ThriveDate. Once the maintainer of Flourish changed it to a protected property, I was able to use it and thus adequately extend fDate.
Since you never know who might need to extend your class, and by how much, in the future, it's always best to make every internal property protected, unless there are great reasons for the property to never be modified by subclasses.
TL;DR: Private properties should be as rare as public properties: e.g. used almost never.
With protected its possible for an object of the class or any subclass to access that property. So its useful, if you want this restriction.
This is not strictly necessary, you can also make every property public, but then you will lose every control, who access and/or changes it. Also others may get confused, what all these "public properties" are good for, for which they have access to.
On the other hand you can make every property private, but then also every subclass can not access it anymore.
What about a real life example:
<?
// burguers.php
/* abstract */ class BurguerClass {
// nobody knows about these secret function
private function addSecretRecipeSauce() { ... }
// these one can can change in subclasses
// cannot be called globally
protected /* virtual */ function addBread() { ... }
protected /* virtual */ function addSalad() { ... }
protected /* virtual */ function addMeat() { ... }
protected /* virtual */ function addExtraIngredients() { ... }
// these one it can be access globally
public /* virtual */ function makeBurguer() {
$this->addBread();
$this->addSalad();
$this->addMeat();
$this->addExtraIngredients();
$this->addSecretRecipeSauce();
}
}
/* concrete */ class CheeseBurguerClass extends BurguerClass {
protected /* virtual */ function addCheese() { ... }
public /* override */ function makeBurguer() {
$this->addBread();
$this->addSalad();
$this->addMeat();
$this->addExtraIngredients();
// we add this one:
$this->addCheese();
}
}
/* concrete */ class RanchStyleBurguerClass extends BurguerClass {
protected /* override */ function addExtraIngredients() { ... }
}
/* concrete */ class EastCoastVegetarianStyleBurguerClass extends BurguerClass {
protected /* override */ function addMeat() {
// use soy "meat"
}
protected /* override */ function addExtraIngredients() { ... }
}
function burguers_main() {
$Cheesburguer = new CheeseBurguerClass();
// can be access
$Cheesburguer->makeBurguer();
}
// execute it
burguers_main();
?>
You just open the "Can I have a Cheesburguer" Software Development company. You are the C.E.O., you have several subordinates. You teach subordinates they can make new products based on the "burguerClass" recipe, and make new recipes.
You tell your employees how to "addBread" , "addSalad", "addMeat", "addExtraIngredients", and that operations can be changed by new ones, but cannot sell them separately, only can used in the "makeBurguer" operation.
But, you dont teach your employees the "addSecretRecipe" operation.
The way I understand it is that Private methods and properties cannot be seen by classes that extend; whereas Protected methods and properties can be seen but used only by the class it is defined within.
http://php.net/manual/en/language.oop5.visibility.php
when designing classes, isn't it normal to have private and public
variables or properties.
Granted my OOP experience is very limited, having
access to OOP development in CA-Visual Objects, Clipper, VB, and ASP.
But it was normal to have a series of public properties one could access
directly and then properties that could only be access by the class itself.
Of course in VB and ASP these were defined with Get, Let and Set methods,
but you could still access them directly.
You could also design properties that were read only as well.
Perhaps this is because of operator overloading...
I use protected methods and attributes rather than private mainly for testing purposes. This way it's much easier to create class mocks when writing unit tests.
OOP doesn't ends at organizing your code to classes (as structured programming doesn't ends at splitting code to functions). PHP is a script language, so when using it as OOP language, we should set up contstraints for ourselves.
I was very lucky, when I first met OOP, the language was Java, and the book was Bruce Ekcel - Thinking in Java (you can purchase it on Amazon or other stores, also previous editions can be downloaded from here for free: http://www.mindviewinc.com/Books/downloads.html ). I can recommend that book, even for PHP programmers. If you're not complete beginner, you will understand everything, and adopt it to PHP. I'm trying to programming in PHP like if it were Java (at least, the OOP part; there're no such cool associative arrays in Java, as in PHP).
Also, private, protected, and public categories are not too precise. Public should be split to "API method" and "can be called from other classes" (see "friendly"), protected should distinguish between "should be overwritten" and "must be implemented".
Learn OOP, it's worth.
There's one more thing I wanna to say, a basic pattern of OOP: use getters/setters, don't use public properties, if you use public properties, you just graved it to rock. Say, there's a status flag, now it has 2 possible state values, but if you wanna extend it, all the code must be revised, which use it. Use setState() and getState(), which functions first are simple ($this->state = $param; and return $this->state), but there will be no problem with extending the meaning of state, then you should re-write only these methods, even in the case, if the state is a derived value (e.g. its value is calculated from more flags).
There're several less or more deep similar topics in OOP, this getter/setter is probably the most important of the basic ones.
So, my tips are:
use OOP, it's your friend;
use PHP as like it were JAVA (a strict OOP language), and not like in FORTRAN.
Or in more specific words, is it "ok" to not be relying on setters and getters?
I'm dealing with a class that checks the availability of rooms and sets public properties of which there are more than a dozen. Things such as:
unitNumber
roomTypes ( array )
codeCorporate
codeGroup
numberKids
numberAdults
numberRooms
currency
minRate
maxRate
soapServer
units ( array )
hotelId
And after an object is instantiated those properties are set with $this-> inside various methods. However the code that deals with the object often sets public properties directly instead of using getter/setter methods:
$object->something = 3;
foreach ($object->things as $thing ) { }
If I have the time to refactor this class..
Should I stick all of these properties in a data array that's a private property, and define __set and __get methods?
Should I make a single getter method for each of the properties?
In my opinion, it is rarely a good idea to have any public members. It increases coupling between classes, and makes refactoring very complicated (should you need it.)
Setters/Getters are the way to go, and the very small performance penalty that you pay for it is usually either optimized away, or trumped by elegance.
To answer your question about array vs. single-getter-per-var, it's a matter of taste. I tend to only keep variables of a similar type within an array, and separate the rest.
I personally have yet to find a truly good reason for a public property, though im open for suggestion :-)
Although i much prefer specified getters/setters for each property (whether that's a proxy to a generalized get($name) or not). I assume you have other code already that uses direct assignment so in that case i would say to proceed with using the magic __get/__set methods.
I think most people will recommend using setters & getters. Right now you're limited to simply setting & fetching the property, but what if you want to log when that property is accessed? Or perhaps you want to run the value by a validation function first (email, phonenumber, zip code, etc). Maybe you'll need to call another function, or set another property. I think you see where I'm heading with this. By using setters & getters, you add a valuable layer of encapsulation to your classes, and 99% of the time this is worth the extra typing you'll need to do ;) Imagine trying to do the examples above without setters & getters. It'd be a big headache to say the least.
Edit: I forgot to mention Doctrine. It's an object relation mapper (ORM) that can automatically setup setters & getters for you (amongst other things). You can check it out at http://www.doctrine-project.org/
I would take a step back and ask some more general questions:
Why am I having to expose this much information; what is using it and why?
Is this class really just a data structure without behavior, in which case should be a private class to some other class?
Does this class serve a single purpose, or is it on the path to becoming monolithic?
You may discover that you are able to create views of an instance of a class to export to a database, display in a form, etc. Check out the "Builder" and "Acyclic Visitor" patterns to start with.
Regarding accessors, I do not see a need to use them for what you are describing: retrieving class properties and internal state information, aka a struct. However, for attributes of a class I could see the benefit in certain cases, but more for retrieving attributes, not for mutations of your object's state.
If I may add my grain of salt several months later :
It is very un-OO to have public properties. Everything should be encapsulated, simply because (among other reasons) using direct attribute manipulation doesn't give you ways to easily refactor or perform (more) control checks when some external source modifies the field. For example, let's say you have a class with many fields that is used throughout a project several times, and that project contains several thousands of files; it's a project that has been running and expanded for a few years now. Let's say that the company is changing it's business model, or that a problem is found with some of the field's data type and now is required to have some validation; will you duplicate that validation in all those thousands of source code that is directly accessing the public member? In PHP, the solution may be simple, but not in most OO programming language (i.g. Java). The fact is that OO is based on encapsulation. In short, encapsulation doesn't only produce clean code, but also highly maintainable (not to say cost-effective and cohesive) code.
Your suggestion of having a private member (array) being manipulated by __get / __set is good. This way, if you need some extra validation along the road, simply create your setter and/or your getter and it will be the end of it. Some may argue with that being counter productive as the code completion cannot kick-in on __get / __set. IMHO, relying on code completion is simply lazy coding. But then again, having every member have it's own getter and/or setter allows you to write a more comprehensive API documentation. Personally, I usually use that technique for internal or very general purpose classes. If all your fields do not require any validation, or there are as you said several dozen of them, then using magic methods would be acceptable, in my opinion.
The bottom line is to avoid direct member access on class instances, period. How you decide to achieve this is strictly up to you. Just make sure that the API is well documented the more abstract you make it.
On a final note, in PHP, if you already have classes that are being used that are not encapsulating their fields, for example something like
class SomeObject {
public $foo;
public $bar;
public $baz;
//...
}
you can simply fix this class without having to refactor anything with something like :
class SomeObject {
private $_foo; // having underscore as prefix helps to know what's private/protected
private $_bar; // inside the code.
private $_baz;
public function __get($name) {
$methodName = 'get'.ucfirst($name);
if (method_exists($this, $methodName)) {
return $this->{$methodName}();
} else {
throw new Exception("Method '{$methodName}' does not exist");
}
}
public function __set($name, $value) {
$methodName = 'set'.ucfirst($name);
if (method_exists($this, $methodName)) {
$this->{$methodName}($value);
} else {
throw new Exception("Method '{$methodName}' does not exist");
}
}
public function getFoo() { return $this->_foo; }
public function setFoo($value) { $this->_foo = $value; }
public function getBar() { return $this->_bar; }
public function setBar($value) { $this->_bar = $value; }
public function getBaz() { return $this->_baz; }
public function setBaz($value) { $this->_baz = $value; }
}
And then
$obj = new SomeObject();
$obj->foo = 'Hello world'; // legacy code support
$obj->setFoo('Hello world'); // same thing, but preferred
And you satisfy both the OO paradigm and having direct access to attributes of an instance. You could also have __call() check for prefix 'get' or 'set' and call __get() and __set() accordingly, but I would not go that far, though this would truly enable general purpose classes to access it's private members via ->member and ->getMember()/->setMember()