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"
}