I’ve learned a lot about PHP5 OOP visibility recently. I’m posting a test script that will share some of my discoveries.
Take away:
- Private really does mean private.
- Visibility keywords are honored while cloning
- PHP does not enforce the visibility keywords on variables using a fatal error.
It uses an E_NOTICE : Notice: Undefined property
define( 'SCRIPT_EOL', '<br>' ); abstract class a_base_class { private $name = 'Johannes Kepler'; protected $color = 'Green'; public function __set($name, $value) { throw new Exception( 'a_base_class - Undefined or private property: ' . $name ); } public function __clone() { // this does work - $this->name is private but is accessible in this class $this->name = 'Isaac Newton'; } public function getName() { return $this->name; } public function echoName() { echo $this->name; } } class exampleClass1 extends a_base_class { function __clone() { // this does not work - $this->name is private to ac and can't be modified here $this->name = 'Isaac Newton'; } function echoName() { // this will issue an E_NOTICE because the variable is undefined in this class (private variables do not carry through to descendants) echo $this->name; } function echoColor() { echo $this->color; } } class exampleClass2 extends a_base_class { public function __clone() { $this->color = 'Red'; // without this, $this->name will not get changed to Isaac Newton parent::__clone(); } public function echoColor() { echo $this->color; } } echo '</pre> <hr /> <pre> '; echo '</pre> <h2>exampleClass1</h2> <pre> '; $instance = new exampleClass1(); echo 'calling echoName()' . SCRIPT_EOL; $instance->echoName(); echo 'echo $instance->name' . SCRIPT_EOL; echo $instance->name . SCRIPT_EOL; echo SCRIPT_EOL; echo 'echoing getName()' . SCRIPT_EOL; echo $instance->getName(); // calling public method on base class echo SCRIPT_EOL; echo 'calling echoColor()' . SCRIPT_EOL; $instance->echoColor(); echo SCRIPT_EOL; try { $newInstance = clone $instance; } catch( Exception $e ) { echo SCRIPT_EOL . '------------------------------------------------' . SCRIPT_EOL; echo "Exception Thrown: " . $e->getMessage(); echo SCRIPT_EOL; echo ' '; echo $e->getTraceAsString(); echo ' '; echo SCRIPT_EOL . '------------------------------------------------' . SCRIPT_EOL; } echo SCRIPT_EOL; echo 'var_dump' . SCRIPT_EOL; var_dump( $newInstance ); echo '</pre> <hr /> <pre> '; echo '</pre> <h2>exampleClass2</h2> <pre> '; $instance = new exampleClass2(); echo 'calling echoName()' . SCRIPT_EOL; $instance->echoName(); echo SCRIPT_EOL; echo 'echo $instance->name' . SCRIPT_EOL; echo $instance->name . SCRIPT_EOL; echo 'echoing getName()' . SCRIPT_EOL; echo $instance->getName(); // calling public method on base class echo SCRIPT_EOL; echo 'calling echoColor()' . SCRIPT_EOL; $instance->echoColor(); echo SCRIPT_EOL; try { $newInstance = clone $instance; } catch( Exception $e ) { echo SCRIPT_EOL . '------------------------------------------------' . SCRIPT_EOL; echo "Exception Thrown: " . $e->getMessage(); echo SCRIPT_EOL; echo $e->getTraceAsString(); echo SCRIPT_EOL . '------------------------------------------------' . SCRIPT_EOL; } echo ' '; var_dump( $newInstance ); echo ' ';
Output
exampleClass1
calling echoName()
Notice: Undefined property: exampleClass1::$name in /Users/timgallagher/Desktop/xampp/se/php5oop.php on line 43
echo $instance->name
Notice: Undefined property: exampleClass1::$name in /Users/timgallagher/Desktop/xampp/se/php5oop.php on line 73
echoing getName()
Johannes Kepler
calling echoColor()
Green
————————————————
Exception Thrown: a_base_class – Undefined or private property: name
#0 /Users/timgallagher/Desktop/xampp/se/php5oop.php(37): a_base_class->__set('name', 'Isaac Newton') #1 /Users/timgallagher/Desktop/xampp/se/php5oop.php(84): exampleClass1->__clone() #2 {main}
————————————————
var_dump
Notice: Undefined variable: newInstance in /Users/timgallagher/Desktop/xampp/se/php5oop.php on line 98
NULL
exampleClass2
calling echoName()
Johannes Kepler
echo $instance->name
Notice: Undefined property: exampleClass2::$name in /Users/timgallagher/Desktop/xampp/se/php5oop.php on line 108
echoing getName()
Johannes Kepler
calling echoColor()
Green
object(exampleClass2)#1 (2) { ["name:private"]=> string(12) "Isaac Newton" ["color:protected"]=> string(3) "Red" }