Частный доступ в наследство

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;

В этом коде дочерняя переменная класса $emp может напрямую обращаться к частному члену родительского класса Person. Это не нарушение правила частного доступа?

Он дает ошибку при использовании переменной родительского класса, но работает с переменной класса child!! Может кто-нибудь объяснить, почему?

Ответы

Ответ 1

TL;DR;

$emp->age = 30 не вызывает родительский закрытый член age, он динамически создает свойство дочернего объекта age.

Объяснение

Похож на ошибку, не так ли? Во-первых, пусть вообще комментировать родительский частный член:

<?php

class Person {
    // private $age;
}

class Employee extends Person {
}

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

В строке $emp->age = 10 мы создали новое свойство объекта $emp с именем age и присвоили ему значение 10.

Когда вы определяете родительский элемент как закрытый, дети вообще не видят этого элемента:

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

Ответ 2

Вы назначаете $emp->age = 30; От объекта ($emp).

Теперь, когда вы пытаетесь получить доступ к любой переменной с помощью объекта (который не является переменной-членом), он позволит получить доступ и создать локальную область

Не то, чтобы он не рассматривался как переменная-член этого конкретного класса.

Итак, вот в вашем примере $emp->age, где age не рассматривается как элемент varaible любого из классов, поскольку он не определен в нем.

Вы получите более понятную идею, если попробуете любое имя переменной, которое не является членом какого-либо класса. Вы также получите результат для них.

Например, попробуйте под кодом:

$emp->age_tmp = 30;

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

Итак, проблема не в области видимости, но она создаст другую копию для этой переменной. $emp->age не имеет связи с Person class age

DEMO

Ответ 3

Вы можете определить $object = new stdClass(); и назначить значения синтаксисом $object->field = "value";.

Если суперкласс имеет частное поле. Это поле НЕ СУЩЕСТВУЕТ детям. В вашем коде Сотрудник не имеет возраст поля. И $emp->age = 42; - действительный php-код.

Чтобы сохранить личный возраст в Employee, вам необходимо установить поле как защищенное. Защищенные поля означают, что они являются закрытыми для суперкласса, а также для детей.

Личные частные поля, отсутствуют в детях.

OOP php visability

Ответ 4

В PHP вы можете создавать атрибуты в любом месте кода. Переменная "age" не относится к родительскому классу. u можете попробовать это, если вы хотите

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

Переменная, которая отображается, принадлежит классу employee, а локальная.

Ответ 5

Кстати, если вы хотите, чтобы частное свойство $age не создавалось из экземпляра, вы также можете это сделать:

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

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

__set() - волшебный метод, который автоматически устанавливает новое свойство. В этом случае он не будет работать, если $age будет установлен.

Теперь попробуйте, присвойте значение $age.

3v4l.org