<?php
class Example{
public $pub="public";
private $priv = "private";
protected $prot = "protected";
}
class SubClass extends Example{
}
$ex = new Example();
$sub = new SubClass();
/* called indiviually */
echo $sub->priv; // error
echo $sub->prot; // error
echo "<br/>";
echo $ex->pub; // works
echo $ex->prot; // error
?>
As you can see calling a protected variable with either parent class or subclass is throwing error . So what I can assume is: do something like, $prot acts like private modifier in parent class and we are not allowed to call it from outside the class block . and $prot variable when inherited into subclass it starts acting like private variable because even now it wasn't allowed to call it from outside .
PS : not studied :: scope resolution operator yet . Used only -> arrow and $this
Protected variables are available inside the subclass but will throw an error in any other scope:
<?php
class Example{
public $pub="public";
private $priv = "private";
protected $prot = "protected";
}
class SubClass extends Example{
function get_protected() {
return $this->prot;
}
}
$ex = new Example();
$sub = new SubClass();
/* called indiviually */
echo $sub->priv; // error
echo $sub->prot; // error
echo $sub->get_protected() // works
echo $ex->pub; // works
echo $ex->prot; // error
Related
In the below program the last statement echo $objb->test; should not output any value. The second last statement should throw an error saying that private member cannot be accessed. However, I am getting output 20 when running the program.
Since PHP is loosely type language is the $objb create a new variable outside the class as well...
<?php
error_reporting(E_ALL);
class A {
public $a;
private $test;
protected function sayhello(){
echo "<p>hello class A</p>";
}
}//end of class A
class B extends A {
//private $c;
public function sayhellonew(){
$this->sayhello();
echo "<p>hello class B</p>";
}
}//end of class B
$objb = new B();
$objb->sayhellonew();
$objb->a = 10;
echo $objb->a;
echo "<br>";
$objb->test = 20;
echo $objb->test;
?>
Output
I am getting output 20 why is it working?
Since the $test property is private to A, it is not visible in the scope of B. That means that B can have its own property named $test. When you assign objb->test = 20, that's what you're setting.
The following shows that you're not actually setting the private variable:
class A {
public $a;
private $test = 10;
protected function sayhello(){
echo "<p>hello class A</p>";
}
public function showTestA() {
echo "Test in A = " . $this->test . '<br>';
}
}//end of class A
class B extends A {
//private $c;
public function sayhellonew(){
$this->sayhello();
echo "<p>hello class B</p>";
}
public function showTestB() {
echo "Test in B = " . $this->test . '<br>';
}
}//end of class B
$objb = new B();
$objb->test = 20;
$objb->showTestA();
$objb->showTestB();
This will display:
Test in A = 10
Test in B = 20
Because, you are overriding the parent class' private property with childs class' public property.
It is valid in PHP.
Try adding a new private property $c in class B and try to override it.
You will get an error: Fatal error: Cannot access private property B::$c
Check it here: http://codepad.org/74IgLqYn
Because its not the test same variable that you have declare in it's parent(A) class. In fact its will treat it as public $test; of class B. Check below you will get the issue.
<?php
error_reporting(E_ALL);
class A {
public $a;
private $test;
protected function sayhello(){
echo "<p>hello class A</p>";
}
public function setTest(){
$this->test = "50";
}
}//end of class A
class B extends A {
//private $c;
public function sayhellonew(){
$this->sayhello();
echo "<p>hello class B</p>";
}
}//end of class B
$objb = new B();
$objb->sayhellonew();
$objb->a = 10;
echo $objb->a;
echo "<br>";
$objb->setTest();
echo $objb->test;
?>
CODEPAD.
I have recently started OOP in PHP and I am on visibility concept (public, protected, private). Here I'm confused about protected visibility. Protected members can only be accessible within the declaring clas or a subclass or child class. I have this example on PHP's site:
class MyClass
{
public $public = 'Public';
protected $protected = 'Protected';
private $private = 'Private';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
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->protected; // Fatal Error
echo $obj2->private; // Undefined
$obj2->printHello(); // Shows Public, Protected2, Undefined
In this code in the third last line (echo $obj2->protected; // Fatal Error) it gives fatal error. But isn't protected variable inherited into child class which is MyClass2 in this case? So why this fatal error? Can someone please enlighten me about this?
Protected members can only be accessible within the declaring class or
a subclass or child class.
You must pay attention to the within.
You're getting the fatal error because you're accessing $protected from outside both MyClass2 and MyClass.
Within means that you can access it from MyClass2 like you're doing on MyClass2::printHello() and/or MyClass::printHello() methods.
I am trying to write a PHP class in which I change the visibility of a few methods from protected to public. I believe I remember you can do this in C++, but I did a few searches and I am not coming up with anything for that in PHP. Does anyone know if this is even possible in PHP?
For example, suppose this class:
class ABC {
protected function foo() {
// Do something
}
}
class DEG extends ABC {
// can I make foo public now?
}
You can change the visibility of members when deriving from a base class like this:
class Base
{
protected function foo() {}
}
class Derived extends Base
{
public function foo() { return parent::foo(); }
}
You can also do the same with properties (redefine a protected property as public).
However, be aware that if the base property is private then you will not actually increase its accessibility but rather declare a new property with the same name. This is not an issue with functions, as if you tried to call a private base method you would immediately get a runtime error.
You can overwrite a method in a derived class to highten it´s visibility (e.g. protected->public). Make the new function return it´s parent.
You cannot do so to limit it´s visibility (e.g. public->protected), but you can implement a method that checks the backtrace for the caller and thwors an exception if it´s a foreign class.
You can always use the reflection API to do all kinds of changes to the visibility.
Yes, it can be done. Quoting from PHP manual..
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.
And the example from there as well..
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
Edit : Yes, you can change visibility of public and protected members. Another example from PHP manual..
/**
* 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
?>
I saw this example from php.net:
<?php
class MyClass {
const MY_CONST = "yonder";
public function __construct() {
$c = get_class( $this );
echo $c::MY_CONST;
}
}
class ChildClass extends MyClass {
const MY_CONST = "bar";
}
$x = new ChildClass(); // prints 'bar'
$y = new MyClass(); // prints 'yonder'
?>
But $c::MY_CONST is only recognized in version 5.3.0 or later. The class I'm writing may be distributed a lot.
Basically, I have defined a constant in ChildClass and one of the functions in MyClass (father class) needs to use the constant. Any idea?
How about using static::MY_CONST?
Since php 5.3:
Use static::MY_CONST
More details on static
In this case the keyword static is a reference to the actually called class.
This illustrates the difference between static $var, static::$var and self::$var:
class Base {
const VALUE = 'base';
static function testSelf() {
// Output is always 'base', because `self::` is always class Base
return self::VALUE;
}
static function testStatic() {
// Output is variable: `static::` is a reference to the called class.
return static::VALUE;
}
}
class Child extends Base {
const VALUE = 'child';
}
echo Base::testStatic(); // output: base
echo Base::testSelf(); // output: base
echo Child::testStatic(); // output: child
echo Child::testSelf(); // output: base
Also note that the keyword static has 2 quite different meanings:
class StaticDemo {
static function demo() {
// Type 1: `static` defines a static variable.
static $Var = 'bar';
// Type 2: `static::` is a reference to the called class.
return static::VALUE;
}
}
Instead of
$c = get_class( $this );
echo $c::MY_CONST;
Do this
$c = get_class( $this );
echo constant($c . '::MY_CONST');
I couldn't get it to work with const as it prints "yonderyonder" (that's the thing about constants, they don't change), but it works fine with var:
<?php
class MyClass {
var $MY_CONST = "yonder";
public function __construct() {
echo $this->MY_CONST;
}
}
class ChildClass extends MyClass {
var $MY_CONST = "bar";
}
$x = new ChildClass(); // prints 'bar'
$y = new MyClass(); // prints 'yonder'
?>
If you need to access constants, properties, methods of classes or objects you can use reflection, it provides much more details about structure of the object.
example:
class MainClass
{
const name = 'Primary';
public $foo = 'Foo Variable';
}
class ExtendedClass extends MainClass
{
const name = 'Extended';
}
/**
* From Class Name
*/
//get reflection of main class
$mainReflection = new ReflectionClass('MainClass');
if($mainReflection->hasConstant('name'))
var_dump($mainReflection->getConstant('name'));//Primary
//get reflection of extended class
$extendedReflection = new ReflectionClass('ExtendedClass');
if($extendedReflection->hasConstant('name'))
var_dump($extendedReflection->getConstant('name'));//Extended
/**
* From Objects
*/
$main = new MainClass();
$extended = new ExtendedClass();
//get reflection of main class
$mainReflection = new ReflectionObject($main);
if($mainReflection->hasConstant('name'))
var_dump($mainReflection->getConstant('name'));//Primary
//get reflection of extended class
$extendedReflection = new ReflectionObject($extended);
if($extendedReflection->hasConstant('name'))
var_dump($extendedReflection->getConstant('name'));//Extended
I know the manual definition, but from a real life usage standpoint, what's the difference? When would you use one over the other?
EDIT:
use protected methods when you want a child class (one that extends your current (or parent) class) to be able to access methods or variables within the parent.
Here is the PHP Visibility Manual
private can be seen by no other classes except the one the variable/method is contained in.
protected can be seen by any class that is in the same package/namespace.
Code from the manual.
<?php
/**
* 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
?>
When you know that a variable will be used only in that class and not in any other or extending class you would name it private. So if you extend the class and mistakenly name the variable as the name of a private this would give you error and thus prevent you from making mistakes.
If you for example use many pages in your web application and all of the pages are classes that extend one single class that handles header and footer of the page (cause it's always the same) you can override for example the default title of the page which is set up in parent class with protected variable setting.
I hope this helps.