[PHP] Inheritance, protected and reference patterns

Ordinary inherited child → parent reference

Rather than a reference, the child class just has $ parentName defined (inherited).

ex1.php


<?php
class ParentClass1
{
    protected string $parentName = "parent\n";
}

class ChildClass1 extends ParentClass1
{
    public function getParentName(): void
    {
        echo $this->parentName;
    }
}

$child = new ChildClass1;
$child->getParentName();

parent

Static reference Difference between parent and self

ex2_1.php


<?php
class ParentClass2
{
    protected static string $parentName = "parent\n";
}

class ChildClass2 extends ParentClass2
{
    public static function getParentName(): void
    {
        // parent::$parentName and self::$parentName is the same

        echo "test1:" . parent::$parentName;
        echo "test2:" . self::$parentName;   //Inheriting the definition=Has parentName as its own property

        self::$parentName = "child\n";       //Substitution
        echo "test3:" . parent::$parentName;
        echo "test4:" . self::$parentName;   //Inheriting the definition=Has parentName as its own property
    }
}

ChildClass2::getParentName();

test1:parent test2:parent test3:child test4:child

ex2_2.php


<?php
class ParentClass3
{
    protected static string $parentName = "parent\n";
}

class ChildClass3 extends ParentClass3
{
    protected static string $parentName = "child\n"; //Difference from ChildClass2

    public static function getParentName ()
    {
        //When you define a property with the same name in a child class
        // parent::$parentName and self::$parentName will be different

        echo "test1:" . parent::$parentName;
        echo "test2:" . self::$parentName;   //Has parentName as its own property

        self::$parentName = "child2\n";      //Substitution
        echo "test3:" . parent::$parentName;
        echo "test4:" . self::$parentName;   //Has parentName as its own property
    }
}

ChildClass3::getParentName();

test1:parent test2:child test3:parent test4:child2

Ordinary inheritance: Referencing a parent-to-child property (preface)

Same as ex1.php Rather than a reference, the child class just has parentFunction () defined (inherited).

ex3_1.php


<?php
class ParentClass4
{
    protected string $name = "parent\n";

    protected function parentFunction(): void
    {
        echo $this->name;
    }
}

class ChildClass4 extends ParentClass4
{
    protected string $name = "child\n";

    public function callParentFunction(): void
    {
        $this->parentFunction();
    }
}

$child = new ChildClass4;
$child->callParentFunction();

child

Static reference What self points to and delayed static binding

self is the method or property of its owner, static makes child methods and properties visible

ex3_2.php


<?php
class ParentClass5
{
    protected static string $name = "parent\n";

    protected static function parentFunction(): void
    {
        echo self::$name;
        echo static::$name; //Delayed static binding
    }
}

class ChildClass5 extends ParentClass5
{
    protected static string $name = "child\n";

    public static function callParentFunction(): void
    {
        // parent::parentFunction and self::The status of parentFunction
        // ex2_1.php, ex2_2.See php
        self::parentFunction();
    }
}

ChildClass5::callParentFunction();

parent child

ex3_3.php


<?php
class ParentClass6
{
    protected static string $name = "parent\n";

    protected static function parentFunction(): void
    {
        echo self::$name;
        echo static::$name; //Delayed static binding
    }
}

class ChildClass6 extends ParentClass6
{
    protected static string $name = "child\n";

    protected static function parentFunction(): void // ex3_2.Difference from php
    {
        echo self::$name;
        echo static::$name;
    }

    public static function callParentFunction(): void
    {
        // parent::parentFunction and self::The status of parentFunction
        // ex2_1.php, ex2_2.See php
        self::parentFunction();
    }
}

ChildClass6::callParentFunction();

child child

That parents can use the protected child class

Even if it says that it can be cross-referenced, it may not be very detailed because it has few uses. It seems that it can't be used with the \ # Factory pattern, but there are other ways to do it ...

Common misconceptions

\ # Because it's PHP

ex4_0.php


<?php
class ParentClass7
{
    public function getChildName(): void
    {
        echo $this->name;
    }
}

class ChildClass7 extends ParentClass7
{
    protected string $name = "child\n";
}

$parent = new ParentClass7;
$parent->getChildName();       // ""

$parent->name = "parent_name";
var_dump($parent);             //New public property added to parent class
$parent->getChildName();       //It works, but the definition of the child class is irrelevant

object(ParentClass7)#1 (1) {     ["name"]=>     string(11) "parent_name" } parent_name

If you look at the instance, you can read protected if there is extends, and you can not read it if there is no direct relationship.

ex4_1_1.php


<?php
class ParentClass8
{
    public function getChildName(): void
    {
        $child = new ChildClass8; //An instance of this ChildClass($child)And myself($parent)Even if it doesn't seem to have a direct relationship with
        echo $child->name;        //By definition, child protected can be referenced if it is a parent and child
    }

    public function callChildFunction(): void
    {
        ChildClass8::childFunction(); //Even if it's not an instance.
    }
}

class ChildClass8 extends ParentClass8
{
    protected string $name = "child\n";

    protected static function childFunction(): void
    {
        echo "child_function\n";
    }
}

$parent = new ParentClass8;
$parent->getChildName();
$parent->callChildFunction();

child child_function

ex4_1_2.php


<?php
class ParentClass9
{
    public function getChildName(ChildClass9 $child): void
    {
        echo $child->name; //By definition, parent and child can refer to protected child
    }

    public function callChildFunction(ChildClass9 $child): void
    {
        $child->childFunction();
    }
}

class ChildClass9 extends ParentClass9
{
    protected string $name = "child\n";

    protected function childFunction(): void
    {
        echo "child_function\n";
    }
}

$parent = new ParentClass9;
$child = new ChildClass9;
$parent->getChildName($child); //An instance of this ChildClass($child)And myself($parent)Even if there seems to be no direct relationship with
$parent->callChildFunction($child);

child child_function

Of course you can't read without extends

ex4_2.php


<?php
class ParentClass10
{
    public static function getChildName(): void
    {
        $child = new ChildClass10;
        echo $child->name;
    }

    public static function callChildFunction(): void
    {
        ChildClass10::childFunction();
    }
}

class ChildClass10 /* extends ParentClass10 */
{
    protected string $name = "child\n";

    protected static function childFunction(): void
    {
        echo "child_function\n";
    }
}

ParentClass10::getChildName();

Error: Cannot access protected property ChildClass10::$name

Digression

Private of the same class can be read even if the instances are separated

ex5.php


<?php
class Test
{
    private string $name = "";

    public function __construct(string $name = "")
    {
        $this->name = $name;
    }

    public function getName(Test $instance): void
    {
        echo $instance->name;
    }
}

$instanceA = new Test("A");
$instanceB = new Test("B");

$instanceA->getName($instanceB);

B

It's almost the same in other languages, so give it a try.

Recommended Posts

[PHP] Inheritance, protected and reference patterns
Inheritance and interface.
Ruby inheritance and delegation
About encapsulation and inheritance
Basic data type and reference type
Pony and reference capability closure