}
$testObj = new Test();
$testObj2 = new Test();
if ($testObj == $testObj2) {
echo '相等<br>';
} else {
echo '不相等<br>';
}
$testObj2->name = 'jack';
if ($testObj == $testObj2) {
echo '相等<br>';
} else {
echo '不相等<br>';
}
继承
即使父类的某些属性设置为私有的,子类仍然能够继承,但是对子类却是不可见的。当子类对象使用父类的私有属性的时候,会自动触发重载机制,在子类创建一个和父类私有属性同名的属性。此时子类使用的属性并不是父类的私有属性了,而是通过重载创建的和父类私有属性同名的属性罢了。
如果在子类中需要访问其父类的构造方法( 方法的访问修饰符是public/protected)可以使用父类::方法名(或者 parent::方法名)来完成。(推荐使用parent::方法名,并且一般调用父类构造方法都是parent::__construct();)
调用父类的普通方法直接用this->方法名即可。(也可以用父类名::方法名或者 parent::方法名 ,但是不推荐)
继承并不是直接把父类的属性和方法直接拷贝到子类里面来。而是建立了一种关联。原本我以为是直接把父类的属性和方法直接拷贝过来,最后发现只是建立了一种关联。下图证明了不是直接拷贝,当在子类里调用父类的方法时,父类输出自己的属性时输出结果都和初始化不一样了(private属性除外,因为是私有的,子类无法看见,所以子类也无法重写父类的私有属性),如果是直接拷贝的话,那么当调用父类的方法时应该输出100,200,300才对,所以说继承不是直接拷贝。
class A {
public $num1 = 100;
protected $num2 = 200;
private $num3 = 300;
public function show1() {
echo 'num1 = ' . $this->num1 . '<br>';
}
public function show2() {
echo 'num2 = ' . $this->num2 . '<br>';
}
public function show3() {
echo 'num3 = ' . $this->num3 . '<br>';
}
}
class B extends A {
public $num1 = 1;
protected $num2 = 2;
private $num3 = 3;
public function show1() {
echo 'num1 = ' . $this->num1 . '<br>';
parent::show1();
}
public function show2() {
echo 'num2 = ' . $this->num2 . '<br>';
parent::show2();
}
public function show3() {
echo 'num3 = ' . $this->num3 . '<br>';
parent::show3();
}
}
$bObj = new B();
$bObj->show1();
$bObj->show2();
$bObj->show3();
输出结果:
num1 = 1
num1 = 1
num2 = 2
num2 = 2
num3 = 3
num3 = 300
重载
PHP所提供的"重载"(overloading)是指动态地"创建"类属性和方法。我们是通过魔术方法(magic methods)来实现的。
当调用当前环境下未定义或不可见的类属性或方法时,重载方法会被调用。本节后面将使用"不可访问属性(inaccessible properties)"和"不可访问方法(inaccessible methods)"来称呼这些未定义或不可见的类属性或方法。
属性重载只能在对象中进行。在静态方法中,这些魔术方法将不会被调用。所以这些方法都不能被声明为 static。从 PHP5.3.0 起, 将这些魔术方法定义为 static 会产生一个警告。
所有重载方法都必须被声明为public。
这些魔术方法都参数都不能通过引用传递。
PHP中的"重载"与其它绝大多数面向对象语言不同。传统的"重载"是用于提供多个同名的类方法,但各方法的参数类型和个数不同。
因为PHP处理赋值运算的方式,__set()的返回值将被忽略。类似的,在下面这样的链式赋值中,__get()不会被调用。
$a = $obj->b = 8;
在除 isset() 外的其它语言结构中无法使用重载的属性,这意味着当对一个重载的属性使用 empty() 时,重载魔术方法将不会被调用。
为避开此限制,必须将重载属性赋值到本地变量再使用 empty()。
//在对象中调用一个不可访问方法时,__call() 会被调用。
public mixed __call(string $name , array $arguments)
//用静态方式中调用一个不可访问方法时,__callStatic() 会被调用。
public static mixed __callStatic(string $name , array $arguments)
属性重载
我们曾经提过,当我们访问或给一个不可访问(protected/private)的属性或者不存在的属性赋值时,就会调用相应的系统魔术方法__get($property)
、__set($property, $value)
,如果我们不重写这两个方法,当我们给不存在的属性赋值时,系统会自动帮我们创建一个public的属性,我们可以自己重写这两个方法来管理这些这些动态创建的属性。或者直接不让产生动态属性。当我们不重写这两个方法就不可访问属性赋值时,会报致命错误。
示例:
class Obj {
protected $name = 'itbsl';
}
$obj = new Obj();
$obj->name = "jack"; //此处会报致命错误
var_dump($obj);
错误信息为:
Fatal error: Uncaught Error: Cannot access protected property Obj::$name
当我们重写了__set()
方法就没问题了
class Obj {
protected $str = 'itbsl';
public function __set($name, $value)
{
$this->$name = $value;
}
}
$obj = new Obj();
$obj->str = "jack";
var_dump($obj);
属性重载可以帮助我们动态管理新的属性也可以禁止动态创建属性。
(1)动态管理
class Dog {
//定义一个数组,管理我们动态增加的属性和值
private $arr = [];
//这里我们重写__set来管理动