【 PHP 】PHP8に入門してみた 209日目 PHPの基本 ( オブジェクト指向 いろいろなオブジェクト操作)

PHP8技術者認定初級試験 が始まるようなので 試験に向けて (できるだけ)勉強しようと思います! 使用する書籍は独習PHP 第4版(山田 祥寛)|翔泳社の本 (shoeisha.co.jp) となります。

オブジェクト指向

オブジェクトは参照渡し

関数のパラメータとしてインスタンス(オブジェクト)を渡す場合には、デフォルトで「参照渡し」になります。
オブジェクトがメモリ上に存在するアドレスを関数に渡すため関数内でオブジェクトのプロパティやメソッドを変更した場合元のオブジェクトも変更されるためです。

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8" />
    <title>こんにちは!</title>
    <!-- Bootstrapを有効化 -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" />
</head>

<body>
    <?php
    class MyClass
    {
        public $prop = "Hello";
    }

    function modifyObject(MyClass &$obj)
    {
        $obj->prop = "Goodbye";
    }

    $obj = new MyClass();
    echo $obj->prop; // Hello

    modifyObject($obj);
    echo $obj->prop; // Goodbye    

    ?>
</body>

</html>

MyClassというクラスが定義され、そのインスタンスを作成し、$objという変数に代入しています。
次に、modifyObjectという関数が定義され、パラメータの前に&をつけることで、参照渡しにしています。
この関数内では、$obj$propプロパティをGoodbyeに変更しています。
最後に、$obj$propを表示すると参照渡しにより値が変更されていることが確認できます。

参照渡しを使うことで、オブジェクトのコピーを作らずに関数内で変更を加えることができます。
ただし、参照渡しを乱用するとプログラムの複雑性が増しバグを引き起こす原因になることがあるので、注意が必要とのことです。
私はお仕事でコノ事象に出くわしかなり苦労した経験があります😫

ではオブジェクトの「値渡し」できるのでしょうか。

 

オブジェクトの値渡し?

PHP5まではオブジェクトは「値渡し」だったようです。

PHP5からは「参照渡しになり」、

オブジェクトの「値渡し」は、PHPにおいてはデフォルトでサポートされていなくなってしまったようです。(たぶん)
ただし、オブジェクトをコピーすることで実現することが可能です。
cloneキーワードを使用することで、オブジェクトのコピーを作成することができます。

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8" />
    <title>こんにちは!</title>
    <!-- Bootstrapを有効化 -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" />
</head>

<body>
    <?php
    class MyClass
    {
        public $prop = "Hello";
    }

    function modifyObject(MyClass $obj)
    {
        $obj->prop = "Goodbye";
    }

    $obj = new MyClass();
    echo $obj->prop; // Hello

    modifyObject($obj);
    echo $obj->prop; // Goodbye

    ?>
</body>

</html>

オブジェクトを比較する

ブジェクト同士を比較する場合、以下の点に注意する必要があります。

  1. クラスの定義によって比較方法が異なる
    PHPでは、クラス定義によって、オブジェクト同士を比較する方法が異なります。たとえば、あるクラスでは、同じクラスのインスタンス同士ならば、プロパティの値がすべて等しい場合に等しいと判断するように定義されているかもしれませんが、別のクラスでは、オブジェクト同士を完全一致でなければ等しくないと定義されている場合もあります。

    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="UTF-8" />
        <title>こんにちは!</title>
        <!-- Bootstrapを有効化 -->
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" />
    </head>
    
    <body>
        <?php
        class Person
        {
            private $name;
            private $age;
    
            public function __construct($name, $age)
            {
                $this->name = $name;
                $this->age = $age;
            }
    
            public function getName()
            {
                return $this->name;
            }
    
            public function getAge()
            {
                return $this->age;
            }
        }
    
        class Employee
        {
            private $name;
            private $age;
            private $employeeId;
    
            public function __construct($name, $age, $employeeId)
            {
                $this->name = $name;
                $this->age = $age;
                $this->employeeId = $employeeId;
            }
    
            public function getName()
            {
                return $this->name;
            }
    
            public function getAge()
            {
                return $this->age;
            }
    
            public function getEmployeeId()
            {
                return $this->employeeId;
            }
        }
    
    
        $person1 = new Person('Alice', 25);
        $person2 = new Person('Alice', 25);
        $employee1 = new Employee('Bob', 30, '12345');
        $employee2 = new Employee('Bob', 30, '12345');
    
        // Personクラスのオブジェクト同士を比較する
        if ($person1 == $person2) {
            echo 'person1 and person2 are equal' . PHP_EOL;
        } else {
            echo 'person1 and person2 are not equal' . PHP_EOL;
        }
    
        // Employeeクラスのオブジェクト同士を比較する
        if ($employee1 == $employee2) {
            echo 'employee1 and employee2 are equal' . PHP_EOL;
        } else {
            echo 'employee1 and employee2 are not equal' . PHP_EOL;
        }
    
    
        ?>
    </body>
    
    </html>

    Personクラスのオブジェクト同士を比較した場合、名前と年齢が等しいため、等しいと判断されます。
    しかし、Employeeクラスのオブジェクト同士を比較した場合オブジェクト同士が完全一致でないため「等しくない」と判断されます。

  2. 比較演算子の使用による挙動の違い
    PHPにおいて、比較演算子 == と === は、オブジェクト同士を比較する場合には異なる挙動を示します。
    == 演算子は、オブジェクトのプロパティの値が等しい場合に等しいと判断しますが、=== 演算子は、オブジェクトが同じインスタンスである場合に等しいと判断します。
  3. __equals() メソッドの定義が必要な場合がある
    PHPにおいて、オブジェクト同士を比較する際に、== 演算子を使用する場合、オブジェクトに __equals() メソッドが定義されている必要があります。
    このメソッドは、引数に渡されたオブジェクトが等しいかどうかを判断するために使用されます。
    定義されていない場合は、オブジェクト同士を比較する際に予期しない結果が得られる可能性があります。

メモ

この辺りはJava同様に難解ですね

PHPPHP

Posted by raika@blog