The difference between private and protected - php

In PHP there does not seem to be a big disparity between private and protected methods.
I asked why I should use protected in PHP Chatroom and got this answer:
unless you have good reason not to : yes
and good reason is , if you code is closed-source library
and even then , it can be overridden with reflections
So --
If the private method could potentially be overridden with Reflections, what is the point at all in private methods?

private and protected are there to make it easier to write code that does the right thing. As you've noticed, they're not unbreakable -- there's nothing preventing you from bypassing them if you want to. That's because they're meant to protect you from accidentally doing the wrong thing, not from actively trying to.
That you can bypass them with reflection, doesn't mean you should. You can consider private and protected as kinda a "warranty void if broken" sticker; if you ignore them and muck around with stuff yourself directly, the object/class might not behave properly. It has no obligation to at that point, since you've taken it upon yourself to mess with its innards -- and the code that does so is entirely to blame.
Now, as for the question in the title...you use protected to declare the interface specifically for subclasses; you basically declare that you intend for them to use that stuff directly, while private says that you don't. Whether they disregard that is up to them, but if they do, then screw 'em. You tried to warn them.

Yes it can be overridden using reflection but that's not the point, the point is to restrict access to the method under normal use, i.e. if someone is using your class they shouldn't be able to access that method because it violates the contract that class has.
It's private/protected depending on the use of it, so if someone has made a method private then they've done it because you shouldn't need to access it from another class, if they've made it protected then likely they only intended sub classes to be able to access the method.

class GrandPa
{
private $name = 'Mark Henry';
function getName(){
return $this->name;
}
}
class Daddy extends GrandPa
{
function displayGrandPaName()
{
return $this->name;
}
}
$daddy = new Daddy;
echo $daddy->getName(); // work
echo $daddy->displayGrandPaName(); // Error Undefined property:
Try change private $name = 'Mark Henry'; to protected

Related

PHP Private Static Function

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.

Protected functions in PHP [duplicate]

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.

php oops: visibility

I'm revising my OOPs concepts in PHP. I have a simple php code here for practising visibility.
When i declare $name as private in Big_Animal,
1)Why it doesn't throw an error when i try to assign a different value for $name from outside the class (ie. $lion->name="King")?
2)Why it doesn't throw an error when i try to reassign $name in Lion class (ie. $this->name="John").
I'm confused coz as per my knowledge, private properties can only be accessed within the class that defines the property.
The other thing i'm not clear about is protected properties. As per my understanding, protected properties can be accessed only within the class itself and its child classes. Can it be accessed by its grandchild classes?
Thank you.
<?php
abstract class Big_Animal{
private $name="Mary";
abstract public function Greet();
public function Describe(){
return "name: ".$this->name;
}
public function __set($name,$value){
$this->name=$value;
}
public function __get($name){
return $this->name;
}
}
class Lion extends Big_Animal{
public function Greet(){
$this->name="John"; //no error for this
return " roar!";
}
public function Describe(){
return parent::Describe()." I'm a Lion!";
}
}
$lion = new Lion();
$lion->name="King"; //no error for this
echo $lion->Describe();
echo $lion->Greet();
?>
Your magic method accessors (__set and __get) are public in the base, abstract class. They are the ones writing to the private data when you access the property directly. Try commenting out the magic methods and see. Then, the output is "name: Mary I'm a Lion! roar!".
Add this as the first statement in Lion::Describe():
echo "Lion's name: " . $this->name . "\n";
As you can see, the output is now: "Lion's name: King". Both $this->name="John"; and $lion->name="King"; are modifying the public property on Lion class' object. It's unfortunate that you can have both public and private properties of the same name, but you can. They are simply different variables (in different scopes).
Protected properties can be accessed from grandchildren. Most of your properties should be protected, unless you have a really strong reason to protect it (therefore using private). Public properties aren't used much in larger projects (depending on your style). I'd prefer to stick with explicit accessors. As a project progresses and becomes more complex, you'll be glad you chose to use accessors for each variable. I prefer to use a generator that will generate the scaffolding accessors for you. It saves a lot of time, cuts down on errors, and makes the creation of accessors a lot cheaper (and therefore more common).
UPDATE (a response to the comment below):
1) and 2) You're not getting errors because you're editing the Public variable in both of the instances that I listed in my 2) above. Try var_dump($lion):
object(Lion)#1 (2) {
["name":"Big_Animal":private]=>
string(4) "Mary"
["name"]=>
string(4) "John"
}
Also, if you explicitly add a private or protected member variable to the Lion class, you will get the error that you expect. I would agree with you that that's not very intuitive, but appears to be the current reality in PHP.
3) http://www.ibm.com/developerworks/opensource/library/os-php-7oohabits/ has an example of writing public accessors for private member variables (although, again, I'd recommend writing public accessors for protected member variables instead).
Because you are using magic method of __set()
__set() is run when writing data to inaccessible properties.
It is also possible to get the value by $lion->name because you also use __get().
To elaborate on my comment... You are using a function called __set, what this does is that every time you try to set a value on an unknown property on this class, this specific function is called.
In your function, you are always changing the private field name, into the value provided. Since this class has access to it's field, this is set.
Even if you wrote $lion->foo = "bar", the name would be set to bar, due to your function __set
I think the answer for your question is here
Abstract methods cannot be private, because by definition they must be
implemented by a derived class. If you don't want it to be public, it
needs to be protected, which means that it can be seen by derived
classes, but nobody else.

How do I access private attributes in PHP? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Best practices to test protected methods with PHPUnit
class Footer
{
private $_isEnabled;
public function __construct(){
$this->_isEnabled = true;
}
public function disable(){
$this->_isEnabled = false;
}
}
When I am writing a unit test for the disable function after I set _isEanabled to false, I want to assert whether or not it is false.
But how can I access $_isEnabled?
This is my test function:
public function testDisable(){
$footer = new Footer();
$footer->disable();
$this->assertFalse($footer->_isEnable);
}
Short answer:
You cannot. That's what PRIVATE means...
Long answer:
You can do it using reflection:
http://php.net/manual/en/book.reflection.php
It is a bit complicated, though, and adds another layer prone to fail so it is not the best way for testing...
I rather prefer to create a getter function:
public function getEnabled() {
return $this->_isEnabled;
}
But if you have not done it as simple, I think you do not want to create it... but given the alternatives, you may reconsider it.
An accessible property has to be public, I think that is self explanatory. However, you might encounter code where protected and private properties seem accessible in a way similar to accessing public variables.
This is done using the magic getter method:
class Footer
{
private $_isEnabled;
public function __get($propName)
{
if (!isset($this->{$propName}))
{
throw new Exception($propName.' is not set');
}
return $this->{$propName};
}
}
This magic method is invoked each time you try to access a property that either, doesn't exist or isn't public. In short:
$instance->_isEnabled;//will work.
You can alter this method as you like, so that, for example, the underscore isn't required anymore... there's tons of things you can do with this.Refer to the man pages
I doubt getting points by this: the class is not "algebraically" complete. A public function isEnabled() is missing. If the unit test has no info about the state, then other class clients will also miss this info.
A unit test on something private does not help saying anything on the public API, but checks internal operation which should be obvious.
In general it is bad business having unit tests relying on the implementation; then reimplementation makes maintaining unit tests too.

Defaulting to default getter behavior if property does not exit

I'm currently needing to extend a class to add functionality to it (I do not have access to the base class to modify it), and I'm running into an isssue with it.
Basically, I need the magic getter function to return a set of private variables if they are requested, but otherwise default to the default behaviour. I need these properties to be private so as to use the magic setter function to automatically sync some data.
That said, here's some example code:
class newClass extends baseClass {
private $private1;
private $private2;
...
public function __get($name) {
if($name == 'private1') return $this->private1;
if($name == 'private2') return $this->private2;
... (and so on)
// and here, it should default back to it's default behavior (throwing
// an error on getting invalid/inaccessable property, etc.)
// I cannot just use property_exists, because there may or may not be
// private variables in the base class that should not be exposed.
}
public function __set($name,$val) {
// I use this to do some automatic syncing when the two private variables
// above are set. This needs to be triggered, hence the private variables
// in the first place.
}
}
I know, I could use getProperty/setProperty functions, but I would like this to remain as intuitive as possible, despite the argument that performing such operations is counter-intuitive. The two private properties are very much connected to each other. When one of them is set, it is logically going to affect the others.
As of right now, this is the only logical way I can think of to avoid getter/setter functions and maintain the closely bonded sync between properties. If you guys can think of anything else that may be a viable solution, feel free to suggest options :)
PHP does not have a property builtin like other languages, __get and __set are indeed what you should use here. But it's a bit more work to accomplish therefore.
Your problem seems to be property_exists foremost. It's not easily possible to determine the publicity of properties from within the class (except with introspection). But you can use get_object_vars to filter out private variables from the base class at least:
function __get($name) {
static $r; if (!isset($r)) { $r = new ReflectionClass($this); }
if (($p = $r->getProperty($name)) and $p->isPublic()) {
return $this->$name;
}
elseif (method_exists($this, "get_$name")) {
return $this->{"get_$name"}();
}
else trigger_error("inaccessible property ->$name", E_USER_NOTICE);
}
For reverting back to default behaviour the best you can do is to manually output an error message.
Don't do this, use getter/setters. They are exactly the same amount of work as what you are doing here.

Categories