PHP面向对象编程(2.魔术方法)

PHP面向对象编程(2.魔术方法)

魔术方法

魔术方法由系统提供,是在满足某个条件时,由系统自动的调用;所有的魔术方法都是由双下划线开头,程序员在定义函数时不要使用双下划线开头,除非你要使用其魔术功能。

魔术方法列表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
__construct() // 在使用 new 关键字进行类实例化一个对象时自动执行;对对象属性进行初始化
__destruct() // 在对象被销毁(unset或PHP执行结束)时自动执行;释放变量,通常用于释放对象占用的第三方资源
__call() // 当调用方法不存在时,该方法自动调用
__callStatic() // 当调用的静态方法不存在时,自动调用
__get()
__set()
__isset()
__unset()
__sleep()
__wakeup()
__toString() // 在对象被当成字符串使用时自动执行;兼容对象的字符串调用形式,根据用户需求显示出对象的字符串形态。
__set__state()
__clone() // 在克隆(clone)对象时自动执行;在克隆对象时可以同时执行一些其他操作,甚至可以阻止对象被克隆
__invoke() // 在对象被当成函数使用时自动执行;兼容对象的函数调用形式,允许用户像使用函数一样使用对象

访问修饰符

对属性或者方法的访问控制,是通过在前面添加关键字public,protected,private来实现的。

访问权限 public protected private
所有 *
子类 * *
类内 * * *

访问控制符既可以修饰成员属性,也可以修饰成员方法。

__set() 和 __get()

当程序员要在类外给不可访问的属性赋值时,系统会调用 __set方法;当程序员要在类外获取不可访问的属性赋值时,系统会调用 __get方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?php
header('Content-Type:text/html;charset=utf-8');
class A
{
public $name;
protected $food;

/**
* A constructor.
* @param $name
* @param $food
*/
public function __construct($name, $food)
{
$this->name = $name;
$this->food = $food;
}

/**
* @param $pro_name 属性名
* @return mixed|string
*/
public function __get($pro_name)
{
// property_exists() 函数判断属性是否存在
if (property_exists($this, $pro_name)) {
return $this->$pro_name;
} else {
return '该属性不存在';
}
}

/**
* @param $pro_name 表示属性名
* @param $pro_val 表示属性值
*/
public function __set($pro_name, $pro_val)
{
// 判断属性是否存在
if (property_exists($this, $pro_name)) {
return $this->$pro_name = $pro_val;
} else {
return '该属性不存在';
}
}
}

$a = new A('lx', 'xls');
echo $a->food; // 获取受保护的值
// 结果:xls
echo $a->fond = 'nc'; // 修改受保护的值
// 结果:nc

__isset() 和 __unset()

(1) 当对不可访问的属性进行了 isset($对象名->属性),empty($对象名->属性) 操作,那么 __isset() 函数就会被系统调用。

(2) 当对不可访问的属性进行了 unset($对象名->属性),那么 __unset() 函数就会被系统调用。

如果已经使用了 unset() 释放了一个变量之后,再使用 isset() 测试该变量将返回 FALSE。

若使用 isset() 测试一个被设置成 NULL 的变量,将返回 FALSE。同时要注意的是 null 字符(”\0”)并不等于等同于 PHP 的 NULL 常量。

如果一次传入多个参数,那么 isset() 只有在全部参数都已被设置时返回 TRUE,计算过程从左至右,中途遇到没有设置的变量时就会立即停止。

__toString() 函数

当我们希望将一个对象当做字符串来输出时,就会触发 __toString() 魔术方法.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php
header('Content-Type:text/html;charset=utf-8');
class A
{
public $name;
protected $food;

/**
* A constructor.
* @param $name
* @param $food
*/
public function __construct($name, $food)
{
$this->name = $name;
$this->food = $food;
}

// 输出一个对象时,触发该函数,__toString 没有形参,要求返回一个字符串
// 可以通过该函数输出对象信息
public function __toString()
{
return $this->name . $this->food;
}

}

$a = new A('lx', 'xls');
echo $a; // 输出一个对象
// 结果:lsxls

__clone()

当我们需要将一个对象完全的赋值一份, 保证两个对象的属性和属性值一样,但是他们的数据库空间独立,则可以使用对象克隆。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<?php
header('Content-Type:text/html;charset=utf-8');
class A
{
public $name;
protected $food;

/**
* A constructor.
* @param $name
* @param $food
*/
public function __construct($name, $food)
{
$this->name = $name;
$this->food = $food;
}

// 如果程序员防止该类被克隆,则将该 __clone() 声明为 private
public function __clone()
{
echo '__clone被调用';
}

}

$a = new A('lx', 'xls');

//---拷贝赋值
$b = $a;
// 比较两个对象
//当使用比较运算符(==)比较两个变量时,原则是:
//如果两个对象的属性和属性值都相等,而且是同一个对象的实例,那么两个变量相等
if ($a == $b) {
echo '<br/> $a==$b';
}
//判断是否属于同一个类
//结果:$a==$b

// 全等运算符(===),这两个对象变量一定要指向某个类的同一个实例(即同一个对象)
if ($a === $b) {
echo '<br/> $a===$b';
}
//判断是否完全相同
//结果:$a===$b




//---对象克隆会触发 __clone() 魔术方法
$c = clone $a;

if ($a == $c) {
echo '<br/> $a==$c';
}
if ($a === $c) {
echo '<br/> $a===$c';
}
//结果:
//__clone被调用
//$a==$c

__call()

(1) 当我们调了一个不可以访问的成员方法时,__call魔术方法就会被调用。

(2) 不可以访问的成员方法的是指(1. 该成员方法不存在, 2. 成员方法是protected或者 private)

示例 ,通过 __call() 调用受保护(protected)的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?php
class S
{
public $name;
protected $hobby;

/**
* S constructor.
* @param $name
* @param $food
*/
public function __construct($name, $hobby)
{
$this->name = $name;
$this->hobby = $hobby;
}

protected function getLx($n, $p)
{
return $n + $p;
}

// 通过 __call() 函数调用 protected 函数
public function __call($method_name, $parameters)
{
if (method_exists($this, $method_name)) {
return $this->$method_name($parameters[0], $parameters[1]);
} else {
return '无此函数';
}
}
}

$lx = new S('lx', 'xls');
echo $lx->getLx(10, 11);
// 结果:21

__callStatic()

当我们调用一个不可访问(protected/private/不存在)的静态方法时,__callStatic() 魔术方法就会被系统调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
header('Content-Type:text/html;charset=utf-8');
class A
{
public static function __callStatic($method_name, $parameters)
{
// echo $method_name;
// echo '<br/><br/>';
// var_dump($parameters);
if (method_exists(self::class, $method_name)) {
return self::$method_name($parameters[0]);
} else {
return '不存在此静态方法';
}
}

protected static function test1($a)
{
echo '<br/> test1()';
}

private static function test2($b)
{
echo '<br/> test2()';
}
}

A::test1(1);
A::test2(2);
echo A::lx();
// 结果:

//test1()
//test2()不存在此静态方法
文章目录
  1. 1. PHP面向对象编程(2.魔术方法)
    1. 1.1. 魔术方法
    2. 1.2. 访问修饰符
    3. 1.3. __set() 和 __get()
    4. 1.4. __isset() 和 __unset()
    5. 1.5. __toString() 函数
    6. 1.6. __clone()
    7. 1.7. __call()
    8. 1.8. __callStatic()
本站总访问量 | 本页面被访问 | 您是第位小伙伴

© XueSi博客 版权所有 备案号 : 赣ICP备19008485号-1