phpoopvisibilityprivateprotected

Private property in parent class can be accessed and re-assigned through the instance of child class in PHP but protected one can't


I am very confused why $produk1->harga = 500; can still make a change (or re-assign the value 500) to private $harga property despite private $harga in class Produk has PRIVATE visibility ? $product1 is an instance of class Komik.

$produk1 = new Komik("Naruto", "Masashi Kishimoto", "Shonen Jump", 30000, 100);

And by echo $produk1->harga; it prints out 500 and not an ERROR. But when I change the visibility to protected $harga it prints out ERROR. How come? I don't understand. Thank you for the answers.

    <?php
        
        class Produk {
            public $judul = "judul",
                    $penulis = "penulis",
                    $penerbit = "penerbit";
            private $harga;
        
        
            public function __construct($judul, $penulis, $penerbit, $harga) {
                $this->judul = $judul;
                $this->penulis = $penulis;
                $this->penerbit = $penerbit;
                $this->harga = $harga;
            }
        
            public function detailInfo() {
                $str = "{$this->judul} | {$this->penulis}, {$this->penerbit} (Rp.{$this->harga})";
        
                return $str;
            }
        
        }
        
        class Komik extends Produk {
            public $jumlahHalaman = 0;
        
            public function __construct($judul, $penulis, $penerbit, $harga, $jumlahHalaman) {
        
                parent::__construct($judul, $penulis, $penerbit, $harga);
                $this->jumlahHalaman = $jumlahHalaman;
            }
        
            public function detailInfo() {
                $str = "Komik : " . parent::detailInfo() . " - {$this->jumlahHalaman} halaman.";
        
                return $str;
            }
        }
        
        
        class Game extends Produk {
        
            public $jumlahDurasi = 0;
        
            public function __construct($judul, $penulis, $penerbit, $harga, $jumlahDurasi) {
                
                parent::__construct($judul, $penulis, $penerbit, $harga);
                $this->jumlahDurasi = $jumlahDurasi;
            }
        
            public function detailInfo() {
                $str = "Game : " . parent::detailInfo() . " ~ {$this->jumlahDurasi} jam.";
        
                return $str;
            }
        }
        
        
        $produk1 = new Komik("Naruto", "Masashi Kishimoto", "Shonen Jump", 30000, 100);
        $produk2 = new Game("Uncharted", "Neil Druckmann", "Sony Computer", 250000, 5);
        
        
        echo $produk1->detailInfo();
        echo "<br>";
        echo $produk2->detailInfo();
        
        echo "<hr>";
        $produk1->harga = 500;
        echo $produk1->harga;

OUTPUT =

Komik : Naruto | Masashi Kishimoto, Shonen Jump (Rp.30000) - 100 halaman. Game : Uncharted | Neil Druckmann, Sony Computer (Rp.250000) ~ 5 jam.


500

IF $harga property visibility is protected

    <?php
        
        class Produk {
            public $judul = "judul",
                    $penulis = "penulis",
                    $penerbit = "penerbit";
            protected $harga;
.
.
.

OUTPUT =

Fatal error: Uncaught Error: Cannot access protected property Komik::$harga in ...

Error: Cannot access protected property Komik::$harga in ...


Solution

  • It's because private properties are not inherited, and when you are trying to access your private property from child class - PHP can't find it and dynamically creates new public one. See example below. Protected properties are inherited and that's why you can't access them from other parts of code.

    <?php
    
    class A {
        private $property = 100;
        
        public function print() {
            echo $this->property;
        }
    }
    
    class B extends A {}
    
    $b = new B();
    $b->property = 500;
    $b->print(); // 100
    
    var_dump($b);
    
    /* 
    object(B)#1 (2) {
      ["property":"A":private] => int(100)
      ["property"]             => int(500)
    } 
    */