In accordance with the official documentation:
Nesting an anonymous class within another class does not give access to any private or protected method, or external class properties. To use the protected methods and properties of the external class, the anonymous class can extend the external class. To use the private properties of the external class in the anonymous class, they must be passed through the constructor.
That is, the constructor of the anonymous class should be defined by passing the private values to be used. For example:
<?php
class MyClass
{
private $prop = "teste";
public function test()
{
$class = new class($this->prop) {
public function __construct($prop)
{
$this->prop = $prop;
}
public function run()
{
echo $this->prop, PHP_EOL;
}
};
$class->run();
}
}
$obj = new MyClass();
$obj->test();
See working on Ideone
Realize that it is the desired value that must be passed through the constructor. Pass the object $this
as a parameter and trying to access its private attribute within the anonymous class results in a fatal error. See below:
<?php
class MyClass
{
private $prop = "teste";
public function test()
{
$class = new class($this) {
public function __construct($obj)
{
$this->obj = $obj;
}
public function run()
{
echo $this->obj->prop, PHP_EOL;
}
};
$class->run();
}
}
$obj = new MyClass();
$obj->test();
See working on Ideone.
That is, even passing the object itself and using it to access the private attribute within the class itself results in error. This is because PHP interprets the context of the anonymous class as something isolated from the parent class, not assigning access permissions to the private attributes and methods of the object itself.
Changeable or immutable attribute
If the attribute passed to the anonymous class is immutable, it will not change the original value of the attribute in the parent class, except when passing the value by reference. By default, immutable attributes are passed by value in PHP. To check, just try to change the value of $prop
within the anonymous class and then check the value of this attribute in the parent class:
<?php
class MyClass
{
public $prop = "teste";
public function test()
{
$class = new class($this->prop) {
public function __construct($prop)
{
$this->prop = $prop;
}
public function run()
{
$this->prop = "teste na classe anônima";
echo $this->prop, PHP_EOL;
}
};
$class->run();
}
}
$obj = new MyClass();
$obj->test();
echo $obj->prop, PHP_EOL;
See working on Ideone.
The output produced is:
teste na classe anônima
teste
That is, as the attribute is a string and is an immutable type, the value was passed to the anonymous class as value and was not changed in the parent class. Basically the object was copied when passed to the anonymous class and this has no reference to the original object.
If the value is of a mutable type, an object of the Foo class, for example, the behavior is different:
<?php
class Foo {
public function __construct($prop) {
$this->prop = $prop;
}
public function __toString() {
return $this->prop;
}
}
class MyClass
{
public function __construct()
{
$this->prop = new Foo("test");
}
public function test()
{
$class = new class($this->prop) {
public function __construct($prop)
{
$this->prop = $prop;
}
public function run()
{
$this->prop->prop = "Teste na classe anônima";
echo $this->prop, PHP_EOL;
}
};
$class->run();
}
}
$obj = new MyClass();
$obj->test();
echo $obj->prop, PHP_EOL;
See working on Ideone.
The result produced is:
Teste na classe anônima
Teste na classe anônima
That is, the original value of the attribute in the parent class has also been changed. Since the object passed to the anonymous class is mutable, the object is referenced, then any change made within the anonymous class will also affect the object in the parent class, as they are the same object.
The big problem is the encapsulation we can only use from within the anonymous publics, leading us to the old getters and setters, PHP still needs to mature a lot.
– Mystic
I don’t know if defining it as a problem is the right thing to do. It would be necessary to evaluate semantically whether it really makes sense for an anonymous class to have access to private class data. You have the Java documentation link about this?
– Woss
As a programmer for android I use this a lot on account of the "listeners" and from within a "Listener" I have access to members of the main class with Myclass.this.prop, that there is the basics of Java
– Mystic