Access the main class instance from an anonymous one in PHP 7

Asked

Viewed 389 times

3

I’m trying to access the instance of the class where contains an anonymous as we do in Java, example:

JAVA

class MyClass 
{
    private String prop = "test";

    public void test()
    {
        new Runnable() {

            public void run() 
            {
                // Consigo acessar prop a partir daqui
                System.out.println(MyClass.this.prop);
            }

        }.run();
    }
}

PHP 7

<?php

class MyClass
{
    private $prop = "test";

    public function test()
    {
        $class = new class{

            public function run() 
            {
                // ???? como acessar MyClass::$prop daqui de dentro?
            }

        };
    }
}

How to access the Myclass instance from within the anonymous?

2 answers

2


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.

  • 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?

  • 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

1

I think there is no way to make this reference, but you can pass a parameter to the constructor of the anonymous class , for example :

class MyClass
{
    private $prop = "test";

    public function test()
    {
        $class = new class($this->prop){

            protected $prop;
            public function __construct($prop){
                $this->prop = $prop;
            }
            public function run() 
            {
                echo $this->prop;
            }

        };

        $class->run(); //test
    }
}
  • 3

    I posted in the OS in English and in fact everyone pointed out this solution to pass the constructor, unfortunately PHP has been trying to copy Java and others, but it is still just a baby taking the first steps

Browser other questions tagged

You are not signed in. Login or sign up in order to post.