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
的私有成员。这不违反私人访问规则吗?
使用父类变量时出错,但是使用子类变量!!任何人都可以解释原因吗?
答案 0 :(得分:19)
<强> TLDR; 强>
$emp->age = 30
不会调用父私有成员age
,它会动态创建新的子对象属性age
。
<强>解释强>
看起来像个bug,不是吗?首先,让我们注释掉父母的私人成员:
<?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
的{{1}}对象的新属性,并为其指定了值age
。
当您将父成员定义为私有成员时,子成员根本不会看到此成员:
10
答案 1 :(得分:3)
您从对象($emp->age = 30;
)分配$emp
。
现在,当您尝试使用object(不是成员变量)访问任何变量时,它将允许访问并创建本地范围
并不是说它不被视为该特定类的成员变量。
所以在你的示例中$emp->age
,其中age不被视为任何类的成员变量,因为它没有在其中定义。
如果你尝试任何不属于任何类的成员的变量名,你会更清楚。你也会得到他们的结果。
例如,尝试以下代码:
$emp->age_tmp = 30;
echo "<br/> Age : ".$emp->age_tmp;
所以问题不是关于范围,而是会为该变量创建其他副本。 $emp->age
与Person
班级age
答案 2 :(得分:2)
您可以定义$object = new stdClass();
并使用语法$object->field = "value";
指定值。
如果超级班有私人领域。那个字段并不存在于儿童中。在您的代码中,员工没有字段年龄。 $emp->age = 42;
是有效的PHP代码。
要在Employee中保持年龄私密,您需要将字段设置为受保护。受保护的字段意味着它对于超类和儿童都是私有的。
人的私人领域不存在于儿童中。
答案 3 :(得分:1)
在PHP中,您可以在代码中的任何位置创建属性。变量&#34; age&#34;不是父类的。你可以尝试这个,如果你想要
<?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;
?>
显示的变量属于员工类,它是本地的。
答案 4 :(得分:1)
顺便说一句,如果你想从一个实例创建私有属性$age
,你可以这样做:
class Person {
public $name;
private $age; //private access
public function __set($age, $value) {
return false;
}
}
__set()
是一种自动设置新属性的神奇方法。
在这种情况下,当尝试设置$age
时,它将无法工作。
现在尝试一下,为$age
分配一个值。