17
class  Person {
    public  $name;
    private $age; //private access
}

class Employee extends Person{
    public $id;
    public $salary; //class property   
}

$emp = new Employee(); 
$emp->name="ABCD";
$emp->age = 30;
$emp->id=101;
$emp->salary=20000;

echo "<br/> Name : ".$emp->name;
echo "<br/> Age : ".$emp->age;

In this code, the child class variable $emp can access private member of parent class Person directly. Is this not the violation of private access rule?

It gives error when using a parent class variable, but works with child class variable!! Can anyone explain why?

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
  • 1
    You'll see it if you `var_dump($emp)` ... `["age":"Person":private]=> NULL ["age"]=> int(30)` ... the private `Person::age` is NULL but a new, public `Employee::age` was created and set to 30. – CD001 Nov 08 '17 at 10:51
  • For safety reasons I'd never return properties directly. Instead create a method that spits them out – Thielicious Nov 08 '17 at 10:52

5 Answers5

22

TLDR;

$emp->age = 30 does not call parent private member age, it creates new child object property age dynamically.

Explanation

Looks like a bug, doesn't it? Firstly, let's comment out the parent's private member:

<?php

class Person {
    // private $age;
}

class Employee extends Person {
}

$emp = new Employee();
$emp->age = 10;
echo $emp->age . "\n";
//out: 10

In the line $emp->age = 10 we created new property of $emp object named age and assigned it value 10.

When you define your parent's member as private, children don't see this member at all:

<?php

class  Person {
    private $age;

    function __construct() {
        $this->age = 30;
    }

    public function printAge()
    {
        echo sprintf("Parent::age = %s\n", $this->age);
    }
}

class Employee extends Person {
    private $age;

    function __construct() {
        parent::__construct();
        $this->age = 10;
    }

    public function printAge()
    {
        echo sprintf("Employee::age = %s\n", $this->age);
        parent::printAge();
    }
}

$emp = new Employee();
$emp->printAge();

//out:
//Employee::age = 10
//Parent::age = 30
rgettman
  • 176,041
  • 30
  • 275
  • 357
Ivan Kalita
  • 2,197
  • 1
  • 18
  • 31
3

You are assigning $emp->age = 30; From object($emp).

Now when you are trying to access any variable using object(which is not member variable), It will allow access and create local scope

Not that it is not treated as member variable of that particular class.

So here in your example $emp->age where age is not consider as member varaible of any of class as it is not defined in it.

You will get idea more clear if you try any variable name which is not member of any of class. You will get result for them also.

For example try below code:

$emp->age_tmp = 30;

echo "<br/> Age : ".$emp->age_tmp;

So issue is not about scope but it will create other copy for that variable. $emp->age doesn't have any connection with Person class age

DEMO

B. Desai
  • 16,414
  • 5
  • 26
  • 47
2

You can define $object = new stdClass(); and assign values with syntax $object->field = "value";.

If super class have a private field. That field NOT EXISTS in children. In your code Employee do not have field age. And $emp->age = 42; is valid php code.

To keep age private in Employee, you need to set field as protected. Protected fields means that is private for super class and also for children.

Persons's private fields, are not present in childrens.

OOP php visibility

sensorario
  • 20,262
  • 30
  • 97
  • 159
  • The field _exists_ in children...it's just not normally visible or accessible to them. Significant difference. – cHao Nov 08 '17 at 17:54
1

In PHP, you can create attributes anywhere in the code. The variable "age" is not that of the parent class. u can try this if u want

<?php

class  Person {
public  $name = "Scare";
private $age = 30; //private access
protected $gender = "Man";
}

class Employee extends Person{
public $id = 20;
public $salary; //class property   
}

$emp = new Employee(); 
echo $emp->id;
echo $emp->name;
echo $emp->age;
$emp->age = "10";
echo $emp->age;
echo $emp->gender;
?>

The variable who is display belong to the employee class, and it's a local.

Y.op
  • 79
  • 1
  • 1
  • 9
1

By the way, if you want the private property $age not be created from an instance you might as well do this:

class  Person {
    public  $name;
    private $age; //private access

    public function __set($age, $value) {
        return false;
    }
}

__set() is a magic method that automatically sets a new property. Inthis case it won't work when $age is attempted to be set.

Now try it, assign a value to $age.

3v4l.org

Thielicious
  • 4,122
  • 2
  • 25
  • 35