Why does inheritance seem to be working in an unexpected way? - php

MApp uses $database_object. I got an error that I could not use it because it was private. However I changed it to protected and now it works. Note that in the class hierarchy MApp is above MAppAMAdder.
I thought that protected meant that child classes could use the resource not parent classes. Is PHP different from other languages or is my understanding of how inheritance works not correct?
MAppAdder Snippet
class MAppAMAdder extends MApp
{
protected $database_object; // private will cause a fail.
MApp
abstract class MApp extends M
{
protected function getID($pipe)
{
$temp = $this->database_object->_pdoQuery('single', 'pull_id_by_h_token',
array($pipe['server']['smalls']['h_token']));
$pipe['id'] = $temp['id'];
return $pipe;
}
protected function addTweetTop($pipe, $comment)
{
$input = array( $pipe['server']['smalls']['h_token'],
$pipe['server']['smalls']['picture'],
$pipe['server']['smalls']['name'],
$comment,
time(),
$pipe['server']['smalls']['h_file'] );
$this->database_object->_pdoQuery( 'none', 'tweet_insert', $input);
return $pipe;
}
}
Error
Fatal error: Cannot access private property MAppTweet::$database_object in...

In PHP protected means that parent classes can also access the property:
Members declared protected can be accessed only within the class
itself and by inherited and parent classes.
You are correct in that this behavior is different from the "classical" behavior of strongly typed languages such as C++ and Java. In such languages (commonly called statically typed) the compiler prevents you from accessing class members in a way that is not provably correct by issuing a compile-time error. That's why a parent class cannot speculatively access a member defined in a child class: there is no guarantee that the member will be there at runtime.
On the other hand, PHP is dynamically typed and does let you refer to any member, even ones that do not exist at all (the access results to null in that case). The check for the existence of such a member is performed at runtime and can result in a wide array of outcomes (from nothing out of the ordinary to a runtime error in certain cases).

How can the super class use a field that is only defined in the subclass? That can't work properly. You can access any field of the superclass from within the subclass, as long as it is declared as public or protected. private fields are not accessible for the subclass. The superclass however knows nothing about any subclass that might exist.

Related

PHP Class not inheriting constructor from parent [duplicate]

When and why should I use public, private, and protected functions and variables inside a class? What is the difference between them?
Examples:
// Public
public $variable;
public function doSomething() {
// ...
}
// Private
private $variable;
private function doSomething() {
// ...
}
// Protected
protected $variable;
protected function doSomething() {
// ...
}
You use:
public scope to make that property/method available from anywhere, other classes and instances of the object.
private scope when you want your property/method to be visible in its own class only.
protected scope when you want to make your property/method visible in all classes that extend current class including the parent class.
If you don't use any visibility modifier, the property / method will be public.
More: (For comprehensive information)
PHP Manual - Visibility
Public:
When you declare a method (function) or a property (variable) as public, those methods and properties can be accessed by:
The same class that declared it.
The classes that inherit the above declared class.
Any foreign elements outside this class can also access those things.
Example:
<?php
class GrandPa
{
public $name='Mark Henry'; // A public variable
}
class Daddy extends GrandPa // Inherited class
{
function displayGrandPaName()
{
return $this->name; // The public variable will be available to the inherited class
}
}
// Inherited class Daddy wants to know Grandpas Name
$daddy = new Daddy;
echo $daddy->displayGrandPaName(); // Prints 'Mark Henry'
// Public variables can also be accessed outside of the class!
$outsiderWantstoKnowGrandpasName = new GrandPa;
echo $outsiderWantstoKnowGrandpasName->name; // Prints 'Mark Henry'
Protected:
When you declare a method (function) or a property (variable) as protected, those methods and properties can be accessed by
The same class that declared it.
The classes that inherit the above declared class.
Outsider members cannot access those variables. "Outsiders" in the sense that they are not object instances of the declared class itself.
Example:
<?php
class GrandPa
{
protected $name = 'Mark Henry';
}
class Daddy extends GrandPa
{
function displayGrandPaName()
{
return $this->name;
}
}
$daddy = new Daddy;
echo $daddy->displayGrandPaName(); // Prints 'Mark Henry'
$outsiderWantstoKnowGrandpasName = new GrandPa;
echo $outsiderWantstoKnowGrandpasName->name; // Results in a Fatal Error
The exact error will be this:
PHP Fatal error: Cannot access protected property GrandPa::$name
Private:
When you declare a method (function) or a property (variable) as private, those methods and properties can be accessed by:
The same class that declared it.
Outsider members cannot access those variables. Outsiders in the sense that they are not object instances of the declared class itself and even the classes that inherit the declared class.
Example:
<?php
class GrandPa
{
private $name = 'Mark Henry';
}
class Daddy extends GrandPa
{
function displayGrandPaName()
{
return $this->name;
}
}
$daddy = new Daddy;
echo $daddy->displayGrandPaName(); // Results in a Notice
$outsiderWantstoKnowGrandpasName = new GrandPa;
echo $outsiderWantstoKnowGrandpasName->name; // Results in a Fatal Error
The exact error messages will be:
Notice: Undefined property: Daddy::$name
Fatal error: Cannot access private property GrandPa::$name
Dissecting the Grandpa Class using Reflection
This subject is not really out of scope, and I'm adding it here just to prove that reflection is really powerful. As I had stated in the above three examples, protected and private members (properties and methods) cannot be accessed outside of the class.
However, with reflection you can do the extra-ordinary by even accessing protected and private members outside of the class!
Well, what is reflection?
Reflection adds the ability to reverse-engineer classes, interfaces,
functions, methods and extensions. Additionally, they offers ways to
retrieve doc comments for functions, classes and methods.
Preamble
We have a class named Grandpas and say we have three properties. For easy understanding, consider there are three grandpas with names:
Mark Henry
John Clash
Will Jones
Let us make them (assign modifiers) public, protected and private respectively. You know very well that protected and private members cannot be accessed outside the class. Now let's contradict the statement using reflection.
The code
<?php
class GrandPas // The Grandfather's class
{
public $name1 = 'Mark Henry'; // This grandpa is mapped to a public modifier
protected $name2 = 'John Clash'; // This grandpa is mapped to a protected modifier
private $name3 = 'Will Jones'; // This grandpa is mapped to a private modifier
}
# Scenario 1: without reflection
$granpaWithoutReflection = new GrandPas;
# Normal looping to print all the members of this class
echo "#Scenario 1: Without reflection<br>";
echo "Printing members the usual way.. (without reflection)<br>";
foreach($granpaWithoutReflection as $k=>$v)
{
echo "The name of grandpa is $v and he resides in the variable $k<br>";
}
echo "<br>";
#Scenario 2: Using reflection
$granpa = new ReflectionClass('GrandPas'); // Pass the Grandpas class as the input for the Reflection class
$granpaNames=$granpa->getDefaultProperties(); // Gets all the properties of the Grandpas class (Even though it is a protected or private)
echo "#Scenario 2: With reflection<br>";
echo "Printing members the 'reflect' way..<br>";
foreach($granpaNames as $k=>$v)
{
echo "The name of grandpa is $v and he resides in the variable $k<br>";
}
Output:
#Scenario 1: Without reflection
Printing members the usual way.. (Without reflection)
The name of grandpa is Mark Henry and he resides in the variable name1
#Scenario 2: With reflection
Printing members the 'reflect' way..
The name of grandpa is Mark Henry and he resides in the variable name1
The name of grandpa is John Clash and he resides in the variable name2
The name of grandpa is Will Jones and he resides in the variable name3
Common Misconceptions:
Please do not confuse with the below example. As you can still see, the private and protected members cannot be accessed outside of the class without using reflection
<?php
class GrandPas // The Grandfather's class
{
public $name1 = 'Mark Henry'; // This grandpa is mapped to a public modifier
protected $name2 = 'John Clash'; // This grandpa is mapped to a protected modifier
private $name3 = 'Will Jones'; // This grandpa is mapped to a private modifier
}
$granpaWithoutReflections = new GrandPas;
print_r($granpaWithoutReflections);
Output:
GrandPas Object
(
[name1] => Mark Henry
[name2:protected] => John Clash
[name3:GrandPas:private] => Will Jones
)
Debugging functions
print_r, var_export and var_dump are debugger functions. They present information about a variable in a human-readable form. These three functions will reveal the protected and private properties of objects with PHP 5. Static class members will not be shown.
More resources:
The PHP Manual - OOP Properties
The PHP Manual - OOP Visibility
Techflirt.com - Visibility in PHP Classes
Jordizle.com - Public, Private, Protected in PHP 5
private - can be accessed from WITHIN the class only
protected - can be accessed from WITHIN the class and INHERITING classes
public - can be accessed from code OUTSIDE the class as well
This applies to functions as well as variables.
It is typically considered good practice to default to the lowest visibility required as this promotes data encapsulation and good interface design. When considering member variable and method visibility think about the role the member plays in the interaction with other objects.
If you "code to an interface rather than implementation" then it's usually pretty straightforward to make visibility decisions. In general, variables should be private or protected unless you have a good reason to expose them. Use public accessors (getters/setters) instead to limit and regulate access to a class's internals.
To use a car as an analogy, things like speed, gear, and direction would be private instance variables. You don't want the driver to directly manipulate things like air/fuel ratio. Instead, you expose a limited number of actions as public methods. The interface to a car might include methods such as accelerate(), deccelerate()/brake(), setGear(), turnLeft(), turnRight(), etc.
The driver doesn't know nor should he care how these actions are implemented by the car's internals, and exposing that functionality could be dangerous to the driver and others on the road. Hence the good practice of designing a public interface and encapsulating the data behind that interface.
This approach also allows you to alter and improve the implementation of the public methods in your class without breaking the interface's contract with client code. For example, you could improve the accelerate() method to be more fuel efficient, yet the usage of that method would remain the same; client code would require no changes but still reap the benefits of your efficiency improvement.
Edit: Since it seems you are still in the midst of learning object oriented concepts (which are much more difficult to master than any language's syntax), I highly recommend picking up a copy of PHP Objects, Patterns, and Practice by Matt Zandstra. This is the book that first taught me how to use OOP effectively, rather than just teaching me the syntax. I had learned the syntax years beforehand, but that was useless without understanding the "why" of OOP.
The difference is as follows:
Public :: A public variable or method can be accessed directly by any user of the class.
Protected :: A protected variable or method cannot be accessed by users of the class but can be accessed inside a subclass that inherits from the class.
Private :: A private variable or method can only be accessed internally from the class in which it is defined.This means that a private variable or method cannot be called from a child that extends the class.
Visibility Scopes with Abstract Examples :: Makes easy Understanding
This visibility of a property or method is defined by pre-fixing declaration of one of three keyword (Public, protected and private)
Public : If a property or method is defined as public, it means it can be both access and manipulated by anything that can refer to object.
Abstract eg. Think public visibility scope as "public picnic" that anybody can come to.
Protected : when a property or method visibility is set to protected members can only be access within the class itself and by inherited & inheriting classes. (Inherited:- a class can have all the properties and methods of another class).
Think as a protected visibility scope as "Company picnic" where company members and their family members are allowed not the public. It's the most common scope restriction.
Private : When a property or method visibility is set to private, only the class that has the private members can access those methods and properties(Internally within the class), despite of whatever class relation there maybe.
with picnic analogy think as a "company picnic where only the company members are allowed" in the picnic. not family neither general public are allowed.
/**
* Define MyClass
*/
class MyClass
{
public $public = 'Public';
protected $protected = 'Protected';
private $private = 'Private';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
$obj = new MyClass();
echo $obj->public; // Works
echo $obj->protected; // Fatal Error
echo $obj->private; // Fatal Error
$obj->printHello(); // Shows Public, Protected and Private
/**
* Define MyClass2
*/
class MyClass2 extends MyClass
{
// We can redeclare the public and protected method, but not private
protected $protected = 'Protected2';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
$obj2 = new MyClass2();
echo $obj2->public; // Works
echo $obj2->private; // Undefined
echo $obj2->protected; // Fatal Error
$obj2->printHello(); // Shows Public, Protected2, Undefined
Extracted From :
http://php.net/manual/en/language.oop5.visibility.php
⚡️ Here is an easy way to remember the scope of public, protected and private.
PUBLIC:
public scope: A public variable/function is available to both objects and other classes.
PROTECTED:
protected scope: A protected variable/function is available to all the classes that extend the current class.
No! Objects cannot access this scope
PRIVATE:
private scope: A private variable/function is only visible in the current class where it is being defined.
No! Class that extend the current class cannot access this scope.
No! Objects cannot access this scope.
Read the Visibility of a method or variable on PHP Manual.
Considering 'when':
I tend to declare everything as private initially, if I'm not exactly sure. Reason being, that it's usually much easier to turn a private method public than the other way round. That's because you can at least be sure that the private method hasn't been used anywhere but in the class itself. A public method may already be in use everywhere, possibly requiring an extensive re-write.
Update: i go for a default of protected nowadays, because I've come to find that it's good enough for encapsulation and doesn't get in the way when I'm extending classes (which i try to avoid anyway). Only if i have a good reason to use the other two, i will.
A good reason for a private method would be one that implements something inherent to that object that even an extending class should not change (factual reason, in addition to encapsulation, like internal state management). Eventually, it's still easy enough to track down where a protected method is being used usually, so i default to protected nowadays. Maybe not 100% objective "in the trenches" experience, I admit.
For me, this is the most useful way to understand the three property types:
Public: Use this when you are OK with this variable being directly accessed and changed from anywhere in your code.
Example usage from outside of the class:
$myObject = new MyObject()
$myObject->publicVar = 'newvalue';
$pubVar = $myObject->publicVar;
Protected: Use this when you want to force other programmers (and yourself) to use getters/setters outside of the class when accessing and setting variables (but you should be consistent and use the getters and setters inside the class as well). This or private tend to be the default way you should set up all class properties.
Why? Because if you decide at some point in the future (maybe even in like 5 minutes) that you want to manipulate the value that is returned for that property or do something with it before getting/setting, you can do that without refactoring everywhere you have used it in your project.
Example usage from outside of the class:
$myObject = new MyObject()
$myObject->setProtectedVar('newvalue');
$protectedVar = $myObject->getProtectedVar();
Private: private properties are very similar to protected properties. But the distinguishing feature/difference is that making it private also makes it inaccessible to child classes without using the parent class's getter or setter.
So basically, if you are using getters and setters for a property (or if it is used only internally by the parent class and it isn't meant to be accessible anywhere else) you might as well make it private, just to prevent anyone from trying to use it directly and introducing bugs.
Example usage inside a child class (that extends MyObject):
$this->setPrivateVar('newvalue');
$privateVar = $this->getPrivateVar();
Reviving an old question, but I think a really good way to think of this is in terms of the API that you are defining.
public - Everything marked public is part of the API that anyone using your class/interface/other will use and rely on.
protected - Don't be fooled, this is also part of the API! People can subclass, extend your code and use anything marked protected.
private - Private properties and methods can be changed as much as you like. No one else can use these. These are the only things you can change without making breaking changes.
Or in Semver terms:
Changes to anything public or protected should be considered MAJOR changes.
Anything new public or protected should be (at least) MINOR
Only new/changes to anything private can be PATCH
So in terms of maintaining code, its good to be careful about what things you make public or protected because these are the things you are promising to your users.
PHP manual has a good read on the question here.
The visibility of a property or method can be defined by prefixing the declaration with the keywords public, protected or private. Class members declared public can be accessed everywhere. Members declared protected can be accessed only within the class itself and by inherited and parent classes. Members declared as private may only be accessed by the class that defines the member.
They're there to allow for different levels of encapsulation
Variables in PHP are cast in three different type:
Public : values of this variable types are available in all scope and call on execution of you code.
declare as: public $examTimeTable;
Private: Values of this type of variable are only available on only to the class it belongs to.
private $classRoomComputers;
Protected: Values of this class only and only available when Access been granted in a form of inheritance or their child class. generally used :: to grant access by parent class
protected $familyWealth;
Public: is a default state when you declare a variable or method, can be accessed by anything directly to the object.
Protected: Can be accessed only within the object and subclasses.
Private: Can be referenced only within the object, not subclasses.
The mentioned keywords are access modifiers and help us implement Encapsulation (or information hiding). They tell the compiler which other classes should have access to the field or method being defined.
private - Only the current class will have access to the field or method.
protected - Only the current class and subclasses (and sometimes also same-package classes) of this class will have access to the field or method.
public - Any class can refer to the field or call the method.

Protected fields access from brother

I reveal iteresting behavior of php >= 5.2
class A {
protected $a = 'A';
public function __get($f){ return 'field_'.$f; }
}
class B extends A {}
class C extends A {
public function foo() {
$b = new B();
echo $b->a;
}
}
$c = new C();
$c->foo();
I expect it print field_a, but it print A.
Also. If I remove magic from A - I expect fatal error, but it still print A in php>=5.2.
If we overwrite B::$a we get another behavior - fatal error.
Why?
Is it feature or bug?
Fiddles:
- http://3v4l.org/tiOC5 - get foreign field
- http://3v4l.org/uT9PC - get fatal error
This is because of PHP's very funky rules for who can and cannot access class properties.
Read about it here:
http://php.net/manual/en/language.oop5.visibility.php
The key part is this:
The visibility of a property or method can be defined by prefixing the
declaration with the keywords public, protected or private. Class
members declared public can be accessed everywhere. Members declared
protected can be accessed only within the class itself and by
inherited and parent classes. Members declared as private may only be
accessed by the class that defines the member.
Emphasis mine. You are allowed to access the protected variables of any object that inherits from the same class you inherit from, even on another object. This also includes accessing the private properties of other objects of the exact same class.
Whether this is a good idea or a weird feature is up for debate, but it seems to be intended.
I believe if you declare a variable it won't use the __get magic method.
So by declaring protected $a = 'A';, you are excluding a from the __get cycle. It will skip the magic method and go straight for the actual property.
If you look at the documentation for the magic methods __get() and __set() you'll see that they only run in the case of reading/writing to an inaccessible field.
In your example $a is accessible from class C as it's defined as a protected field (inheriting/parent classes can view protected fields/methods). If you change $a to a private field it should have to call the magic method for your example.

What is the difference between public, private, and protected?

When and why should I use public, private, and protected functions and variables inside a class? What is the difference between them?
Examples:
// Public
public $variable;
public function doSomething() {
// ...
}
// Private
private $variable;
private function doSomething() {
// ...
}
// Protected
protected $variable;
protected function doSomething() {
// ...
}
You use:
public scope to make that property/method available from anywhere, other classes and instances of the object.
private scope when you want your property/method to be visible in its own class only.
protected scope when you want to make your property/method visible in all classes that extend current class including the parent class.
If you don't use any visibility modifier, the property / method will be public.
More: (For comprehensive information)
PHP Manual - Visibility
Public:
When you declare a method (function) or a property (variable) as public, those methods and properties can be accessed by:
The same class that declared it.
The classes that inherit the above declared class.
Any foreign elements outside this class can also access those things.
Example:
<?php
class GrandPa
{
public $name='Mark Henry'; // A public variable
}
class Daddy extends GrandPa // Inherited class
{
function displayGrandPaName()
{
return $this->name; // The public variable will be available to the inherited class
}
}
// Inherited class Daddy wants to know Grandpas Name
$daddy = new Daddy;
echo $daddy->displayGrandPaName(); // Prints 'Mark Henry'
// Public variables can also be accessed outside of the class!
$outsiderWantstoKnowGrandpasName = new GrandPa;
echo $outsiderWantstoKnowGrandpasName->name; // Prints 'Mark Henry'
Protected:
When you declare a method (function) or a property (variable) as protected, those methods and properties can be accessed by
The same class that declared it.
The classes that inherit the above declared class.
Outsider members cannot access those variables. "Outsiders" in the sense that they are not object instances of the declared class itself.
Example:
<?php
class GrandPa
{
protected $name = 'Mark Henry';
}
class Daddy extends GrandPa
{
function displayGrandPaName()
{
return $this->name;
}
}
$daddy = new Daddy;
echo $daddy->displayGrandPaName(); // Prints 'Mark Henry'
$outsiderWantstoKnowGrandpasName = new GrandPa;
echo $outsiderWantstoKnowGrandpasName->name; // Results in a Fatal Error
The exact error will be this:
PHP Fatal error: Cannot access protected property GrandPa::$name
Private:
When you declare a method (function) or a property (variable) as private, those methods and properties can be accessed by:
The same class that declared it.
Outsider members cannot access those variables. Outsiders in the sense that they are not object instances of the declared class itself and even the classes that inherit the declared class.
Example:
<?php
class GrandPa
{
private $name = 'Mark Henry';
}
class Daddy extends GrandPa
{
function displayGrandPaName()
{
return $this->name;
}
}
$daddy = new Daddy;
echo $daddy->displayGrandPaName(); // Results in a Notice
$outsiderWantstoKnowGrandpasName = new GrandPa;
echo $outsiderWantstoKnowGrandpasName->name; // Results in a Fatal Error
The exact error messages will be:
Notice: Undefined property: Daddy::$name
Fatal error: Cannot access private property GrandPa::$name
Dissecting the Grandpa Class using Reflection
This subject is not really out of scope, and I'm adding it here just to prove that reflection is really powerful. As I had stated in the above three examples, protected and private members (properties and methods) cannot be accessed outside of the class.
However, with reflection you can do the extra-ordinary by even accessing protected and private members outside of the class!
Well, what is reflection?
Reflection adds the ability to reverse-engineer classes, interfaces,
functions, methods and extensions. Additionally, they offers ways to
retrieve doc comments for functions, classes and methods.
Preamble
We have a class named Grandpas and say we have three properties. For easy understanding, consider there are three grandpas with names:
Mark Henry
John Clash
Will Jones
Let us make them (assign modifiers) public, protected and private respectively. You know very well that protected and private members cannot be accessed outside the class. Now let's contradict the statement using reflection.
The code
<?php
class GrandPas // The Grandfather's class
{
public $name1 = 'Mark Henry'; // This grandpa is mapped to a public modifier
protected $name2 = 'John Clash'; // This grandpa is mapped to a protected modifier
private $name3 = 'Will Jones'; // This grandpa is mapped to a private modifier
}
# Scenario 1: without reflection
$granpaWithoutReflection = new GrandPas;
# Normal looping to print all the members of this class
echo "#Scenario 1: Without reflection<br>";
echo "Printing members the usual way.. (without reflection)<br>";
foreach($granpaWithoutReflection as $k=>$v)
{
echo "The name of grandpa is $v and he resides in the variable $k<br>";
}
echo "<br>";
#Scenario 2: Using reflection
$granpa = new ReflectionClass('GrandPas'); // Pass the Grandpas class as the input for the Reflection class
$granpaNames=$granpa->getDefaultProperties(); // Gets all the properties of the Grandpas class (Even though it is a protected or private)
echo "#Scenario 2: With reflection<br>";
echo "Printing members the 'reflect' way..<br>";
foreach($granpaNames as $k=>$v)
{
echo "The name of grandpa is $v and he resides in the variable $k<br>";
}
Output:
#Scenario 1: Without reflection
Printing members the usual way.. (Without reflection)
The name of grandpa is Mark Henry and he resides in the variable name1
#Scenario 2: With reflection
Printing members the 'reflect' way..
The name of grandpa is Mark Henry and he resides in the variable name1
The name of grandpa is John Clash and he resides in the variable name2
The name of grandpa is Will Jones and he resides in the variable name3
Common Misconceptions:
Please do not confuse with the below example. As you can still see, the private and protected members cannot be accessed outside of the class without using reflection
<?php
class GrandPas // The Grandfather's class
{
public $name1 = 'Mark Henry'; // This grandpa is mapped to a public modifier
protected $name2 = 'John Clash'; // This grandpa is mapped to a protected modifier
private $name3 = 'Will Jones'; // This grandpa is mapped to a private modifier
}
$granpaWithoutReflections = new GrandPas;
print_r($granpaWithoutReflections);
Output:
GrandPas Object
(
[name1] => Mark Henry
[name2:protected] => John Clash
[name3:GrandPas:private] => Will Jones
)
Debugging functions
print_r, var_export and var_dump are debugger functions. They present information about a variable in a human-readable form. These three functions will reveal the protected and private properties of objects with PHP 5. Static class members will not be shown.
More resources:
The PHP Manual - OOP Properties
The PHP Manual - OOP Visibility
Techflirt.com - Visibility in PHP Classes
Jordizle.com - Public, Private, Protected in PHP 5
private - can be accessed from WITHIN the class only
protected - can be accessed from WITHIN the class and INHERITING classes
public - can be accessed from code OUTSIDE the class as well
This applies to functions as well as variables.
It is typically considered good practice to default to the lowest visibility required as this promotes data encapsulation and good interface design. When considering member variable and method visibility think about the role the member plays in the interaction with other objects.
If you "code to an interface rather than implementation" then it's usually pretty straightforward to make visibility decisions. In general, variables should be private or protected unless you have a good reason to expose them. Use public accessors (getters/setters) instead to limit and regulate access to a class's internals.
To use a car as an analogy, things like speed, gear, and direction would be private instance variables. You don't want the driver to directly manipulate things like air/fuel ratio. Instead, you expose a limited number of actions as public methods. The interface to a car might include methods such as accelerate(), deccelerate()/brake(), setGear(), turnLeft(), turnRight(), etc.
The driver doesn't know nor should he care how these actions are implemented by the car's internals, and exposing that functionality could be dangerous to the driver and others on the road. Hence the good practice of designing a public interface and encapsulating the data behind that interface.
This approach also allows you to alter and improve the implementation of the public methods in your class without breaking the interface's contract with client code. For example, you could improve the accelerate() method to be more fuel efficient, yet the usage of that method would remain the same; client code would require no changes but still reap the benefits of your efficiency improvement.
Edit: Since it seems you are still in the midst of learning object oriented concepts (which are much more difficult to master than any language's syntax), I highly recommend picking up a copy of PHP Objects, Patterns, and Practice by Matt Zandstra. This is the book that first taught me how to use OOP effectively, rather than just teaching me the syntax. I had learned the syntax years beforehand, but that was useless without understanding the "why" of OOP.
The difference is as follows:
Public :: A public variable or method can be accessed directly by any user of the class.
Protected :: A protected variable or method cannot be accessed by users of the class but can be accessed inside a subclass that inherits from the class.
Private :: A private variable or method can only be accessed internally from the class in which it is defined.This means that a private variable or method cannot be called from a child that extends the class.
Visibility Scopes with Abstract Examples :: Makes easy Understanding
This visibility of a property or method is defined by pre-fixing declaration of one of three keyword (Public, protected and private)
Public : If a property or method is defined as public, it means it can be both access and manipulated by anything that can refer to object.
Abstract eg. Think public visibility scope as "public picnic" that anybody can come to.
Protected : when a property or method visibility is set to protected members can only be access within the class itself and by inherited & inheriting classes. (Inherited:- a class can have all the properties and methods of another class).
Think as a protected visibility scope as "Company picnic" where company members and their family members are allowed not the public. It's the most common scope restriction.
Private : When a property or method visibility is set to private, only the class that has the private members can access those methods and properties(Internally within the class), despite of whatever class relation there maybe.
with picnic analogy think as a "company picnic where only the company members are allowed" in the picnic. not family neither general public are allowed.
/**
* Define MyClass
*/
class MyClass
{
public $public = 'Public';
protected $protected = 'Protected';
private $private = 'Private';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
$obj = new MyClass();
echo $obj->public; // Works
echo $obj->protected; // Fatal Error
echo $obj->private; // Fatal Error
$obj->printHello(); // Shows Public, Protected and Private
/**
* Define MyClass2
*/
class MyClass2 extends MyClass
{
// We can redeclare the public and protected method, but not private
protected $protected = 'Protected2';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
$obj2 = new MyClass2();
echo $obj2->public; // Works
echo $obj2->private; // Undefined
echo $obj2->protected; // Fatal Error
$obj2->printHello(); // Shows Public, Protected2, Undefined
Extracted From :
http://php.net/manual/en/language.oop5.visibility.php
⚡️ Here is an easy way to remember the scope of public, protected and private.
PUBLIC:
public scope: A public variable/function is available to both objects and other classes.
PROTECTED:
protected scope: A protected variable/function is available to all the classes that extend the current class.
No! Objects cannot access this scope
PRIVATE:
private scope: A private variable/function is only visible in the current class where it is being defined.
No! Class that extend the current class cannot access this scope.
No! Objects cannot access this scope.
Read the Visibility of a method or variable on PHP Manual.
Considering 'when':
I tend to declare everything as private initially, if I'm not exactly sure. Reason being, that it's usually much easier to turn a private method public than the other way round. That's because you can at least be sure that the private method hasn't been used anywhere but in the class itself. A public method may already be in use everywhere, possibly requiring an extensive re-write.
Update: i go for a default of protected nowadays, because I've come to find that it's good enough for encapsulation and doesn't get in the way when I'm extending classes (which i try to avoid anyway). Only if i have a good reason to use the other two, i will.
A good reason for a private method would be one that implements something inherent to that object that even an extending class should not change (factual reason, in addition to encapsulation, like internal state management). Eventually, it's still easy enough to track down where a protected method is being used usually, so i default to protected nowadays. Maybe not 100% objective "in the trenches" experience, I admit.
For me, this is the most useful way to understand the three property types:
Public: Use this when you are OK with this variable being directly accessed and changed from anywhere in your code.
Example usage from outside of the class:
$myObject = new MyObject()
$myObject->publicVar = 'newvalue';
$pubVar = $myObject->publicVar;
Protected: Use this when you want to force other programmers (and yourself) to use getters/setters outside of the class when accessing and setting variables (but you should be consistent and use the getters and setters inside the class as well). This or private tend to be the default way you should set up all class properties.
Why? Because if you decide at some point in the future (maybe even in like 5 minutes) that you want to manipulate the value that is returned for that property or do something with it before getting/setting, you can do that without refactoring everywhere you have used it in your project.
Example usage from outside of the class:
$myObject = new MyObject()
$myObject->setProtectedVar('newvalue');
$protectedVar = $myObject->getProtectedVar();
Private: private properties are very similar to protected properties. But the distinguishing feature/difference is that making it private also makes it inaccessible to child classes without using the parent class's getter or setter.
So basically, if you are using getters and setters for a property (or if it is used only internally by the parent class and it isn't meant to be accessible anywhere else) you might as well make it private, just to prevent anyone from trying to use it directly and introducing bugs.
Example usage inside a child class (that extends MyObject):
$this->setPrivateVar('newvalue');
$privateVar = $this->getPrivateVar();
Reviving an old question, but I think a really good way to think of this is in terms of the API that you are defining.
public - Everything marked public is part of the API that anyone using your class/interface/other will use and rely on.
protected - Don't be fooled, this is also part of the API! People can subclass, extend your code and use anything marked protected.
private - Private properties and methods can be changed as much as you like. No one else can use these. These are the only things you can change without making breaking changes.
Or in Semver terms:
Changes to anything public or protected should be considered MAJOR changes.
Anything new public or protected should be (at least) MINOR
Only new/changes to anything private can be PATCH
So in terms of maintaining code, its good to be careful about what things you make public or protected because these are the things you are promising to your users.
PHP manual has a good read on the question here.
The visibility of a property or method can be defined by prefixing the declaration with the keywords public, protected or private. Class members declared public can be accessed everywhere. Members declared protected can be accessed only within the class itself and by inherited and parent classes. Members declared as private may only be accessed by the class that defines the member.
They're there to allow for different levels of encapsulation
Variables in PHP are cast in three different type:
Public : values of this variable types are available in all scope and call on execution of you code.
declare as: public $examTimeTable;
Private: Values of this type of variable are only available on only to the class it belongs to.
private $classRoomComputers;
Protected: Values of this class only and only available when Access been granted in a form of inheritance or their child class. generally used :: to grant access by parent class
protected $familyWealth;
Public: is a default state when you declare a variable or method, can be accessed by anything directly to the object.
Protected: Can be accessed only within the object and subclasses.
Private: Can be referenced only within the object, not subclasses.
The mentioned keywords are access modifiers and help us implement Encapsulation (or information hiding). They tell the compiler which other classes should have access to the field or method being defined.
private - Only the current class will have access to the field or method.
protected - Only the current class and subclasses (and sometimes also same-package classes) of this class will have access to the field or method.
public - Any class can refer to the field or call the method.

couple of questions about OO and classes in PHP

I am learning about OO and classes, I have a couple of questions about OO and classes in PHP
As I understand it, a class that extends another class simply means that the class that extends the other class has access to the variables/properties and the functions/methods of the class that it is extending from. Is this correct?
I know that a static method or property are basically the same as a procedural function or variable outside of a class and can be used pretty much anywhere. Is this correct?
Public means any class can access it and Private means only the class that is is encapsulated in or a class that is extended from the owner of can access and use. Is this correct?
1) Yes, that's correct. A child class inherits any protected or public properties and methods of its parent. Anything declared private can not be used.
2) This is true. As long as the class is loaded (this goes well with your autoloading question from before), you can access static methods via the scope resolution operator (::), like this: ClassName::methodName();
3) You have the meaning of public correct, but as I mentioned earlier, private methods can only be used by the class they are declared in.
class parentClass
{
private $x;
public $y;
}
class childClass extends parentClass
{
public function __construct() {
echo $this->x;
}
}
$z = new childClass();
The above code will result in a NOTICE error being triggered, as $x is not accessible by childClass.
Notice: Undefined property:
childClass::$x
If $x was declared protected instead, then childClass would have access. Edit: A property declared as protected is accessible by the class that declares it and by any child classes that extend it, but not to the "outside world" otherwise. It's a nice intermediate between public and private.
For 1. As I understand it, a class that extends another class simply means that the class that extends the other class has access to the variables/properties and the functions/methods of the class that it is extending from. Is this correct?
ANS: That is correct but that is not all. The extending class can also customize the extended class by overriding the method of the extended class. And ofcouse, it can also extend the super class functionality by adding new fields and methods.
For 2. I know that a static method or property are basically the same as a procedural function or variable outside of a class and can be used pretty much anywhere. Is this correct?
ANS: Yes that is correct and as zombat said as long as the class is public and loaded and the property and method is public. In other word, you are using the class as name space of those elements.
For 3. Public means any class can access it and Private means only the class that is is encapsulated in or a class that is extended from the owner of can access and use. Is this correct?
ANS: Think of it as physical properties, public computer (at a library) can be used by everyone and your private computer (supposibly) can only be used by you.
Just to added to Zambat comment.
There's very little need to declare anything private, as a general rule use protected instead.

Method accessing protected property of another object of the same class

Should an object's method be able to access a protected property of another object of the same class?
I'm coding in PHP, and I just discovered that an object's protected property is allowed to be accessed by a method of the same class even if not of the same object.
In the example, at first, you'll get "3" in the output - as function readOtherUser will have successfully accessed the value -, and after that a PHP fatal error will occur - as the main program will have failed accessing the same value.
<?php
class user
{
protected $property = 3;
public function readOtherUser ()
{
$otherUser = new user ();
print $otherUser->property;
}
}
$user = new user ();
$user->readOtherUser ();
print $user->property;
?>
Is this a PHP bug or is it the intended behaviour (and I'll have to relearn this concept… :)) (and are there references to the fact)? How is it done in other programming languages?
Thanks!
This is intended. It's even possible to access the private members of the same class. So think of the modifiers to be class wise modifiers, not objectwise modifiers.
PHP is not the only language that has this feature. Java for example has this too.
It's intended behavior. A protected variable or function means that it can be accessed by the same class or any class that inherits from that class. A protected method may only be called from within the class, e.g. you cannot call it like this:
$object = new MyClass();
$object->myProtectedFunction();
This will give you an error. However, from within the defined class 'MyClass', you can perfectly call the protected function.
Same applies for variabeles. Summarized:
use PROTECTED on variables and functions when:
1. outside-code SHOULD NOT access this property or function.
2. extending classes SHOULD inherit this property or function.

Categories