PHP面向对象

1 类与对象

1.1 类与对象的关系

一个类可以创建多个对象。

不同的对象的标识符是不一样的。

1.2 对象的传递方式

实例1:

<?php
class Person
{
    public $name;
    public $age;
}

$p1 = new Person;
$p1->name = '金角大王';
$p1->age = 400;

$p2 = $p1;                          //是值传递,拷贝的是对象标识符,并指向相同的数据空间

$p2->name = '银角大王';

echo '<pre>';
echo 'p1 name = ' . $p1->name;      // 银角大王
echo 'p2 name = ' . $p2->name;      // 银角大王

运行结果:

p1 name = 银角大王p2 name = 银角大王

实例2:

<?php
class Person
{
    public $name;
}

$p1 = new Person;
$p1->name = 'aa';
$p2 = $p1;
$p2 = 'abc';        // 可以认为对象标识符变成了abc,并且断开与数据的链接
echo $p1->name;     // 输出aa $p2标识符的改变不影响$p1的数据

实例3:

<?php
class Person
{
    public $name;
}
 
$p1 = new Person;
$p1->name = 'aa';
$p2 = &$p1;
$p2 = 'abc';        // 可以认为两个对象标识符指向同一个,并将对象标识符改为abc
echo $p1->name;     // 此时报错

2 构造函数与析构函数

2.1 构造函数

2.1.1 基本语法:

<?php
class 类名{
    // 构造函数
    访问修饰符 function __construct(){
        // 可以对成员属性进行初始化
    }
}

2.1.2 注意事项:

  1. 在创建一个类的新对象时,系统会自动的调用该类的构造方法完成对新对象的初始化。
  2. 在一个类中,构造函数有且只能有一个, 如果定义多个,就会报错。

2.2 析构函数

2.2.1 说明

析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。

  1. 某个对象的所有引用都被删除
  2. (1)使用unset(对象名), 将对象销毁

    (2)$对象名 = null;

    (3)$对象名 = ‘abc’;

  3. 显示销毁

上面写的三种方式,都是显示销毁, 所谓显示销毁就是程序员主动的删除对象引用。

如果程序员不去显示销毁对象,那么在程序执行完毕后,这个对象就会被系统销毁,这个就是系统销毁

2.2.2 基本语法

<?php
class 类名{
    public function __destruct(){
        // 函数体
        // 析构函数最重要的作用,就是释放对象创建的资源
        // 比如:数据库连接、文件句柄、绘图句柄
    }
}

3 魔术方法

魔术方法是在满足某个条件(一会一个一个的说明)时,有系统自动的调用

clip_image001

3.1 __get()和__set()方法

3.1.1 基本介绍

(1)当程序员去使用不可以访问的属性时,系统就会调用__get方法。当程序员去给不可以访问的属性直接赋值,系统就会调用__set()方法。

(2)不可以访问的属性是指属性不存在、或直接访问了protected、private属性。

3.1.2 举例说明

<?php
class Mokey
{
	public $name;
	protected $food;

	public function __construct($name, $food){
		$this->name = $name;
		$this->food = $food;
	}

	// 如果对象中不存在某个成员属性,或属性是被protected、private访问符修饰的,则系统自动调用__get()魔术方法
	public function __get($pro_name){
		if(!property_exists($this, $pro_name)){     // 检查对象或类是否具有该属性
			echo '不存在您要找的成员属性<br>';
		}else{
			echo '存在您要找的成员属性,但该属性是被protected、private访问符修饰的<br>';
		}
	}


	public function __set($pro_name, $pro_val){
		if(!property_exists($this, $pro_name)){     // 检查对象或类是否具有该属性
			echo '不存在您要找的成员属性,无法赋值<br>';
		}else{
			echo '存在您要找的成员属性,但该属性是被protected、private访问符修饰的,可以进行赋值<br>';
		}
	}


}

$mokey1 = new Mokey('妖猴', '小孩');
$mokey1->food;		// 访问被protected、private访问符修饰的成员属性,自动调用__get()魔术方法
$mokey1->age;	// 访问不存在的成员属性,自动调用__get()魔术方法

$mokey1->food = '鱼';	// 给被protected、private访问符修饰的成员属性赋值,自动调用__set()魔术方法
$mokey1->age = '400';	// 给不存在的成员属性赋值,自动调用__set()魔术方法

运行结果:

存在您要找的成员属性,但该属性是被protected、private访问符修饰的
不存在您要找的成员属性
存在您要找的成员属性,但该属性是被protected、private访问符修饰的,可以进行赋值
不存在您要找的成员属性,无法赋值

3.2 __isset()和__unset()方法

3.2.1 基本介绍

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

(2)不可以访问的属性是指属性不存在、或直接访问了protected、private属性。

3.2.2 举例说明

<?php
class Cat
{
	public $name;
	private $food;

	public function __construct($name, $food){
		$this->name = $name;
		$this->food = $food;
	}

	public function __isset($pro_name){
		if(!property_exists($this, $pro_name)){
			echo '不存在该成员属性<br>';
		}else{
			echo '存在该成员属性,但该属性是被protected、private访问符修饰的<br>';
		}
	}

	public function __unset($pro_name){
		if(!property_exists($this, $pro_name)){
			echo '不存在该成员属性<br>';
		}else{
			echo '存在该成员属性,但该属性是被protected、private访问符修饰的<br>';
		}
	}
}

$cat1 = new Cat('波斯猫', '鱼');
if(isset($cat1->food)){			// food属性存在,但该属性是被private修饰的,自动调用__isset()函数
	echo 'food属性是存在的';
}

if(isset($cat1->age)){			// age属性不存在,自动调用__isset()函数
	echo 'age属性是存在的';
}

unset($cat1->food);				// food属性存在,但该属性是被private修饰的,自动调用__unset()函数
unset($cat1->age);				// age属性不存在,自动调用__unset()方法

运行结果:

存在该成员属性,但该属性是被protected、private访问符修饰的
不存在该成员属性
存在该成员属性,但该属性是被protected、private访问符修饰的
不存在该成员属性

3.3 __toString()方法

3.3.1 基本介绍

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

3.3.2 举例说明

<?php
class Sheep
{
	public $name;
	protected $food;

	public function __construct($name, $food){
		$this->name = $name;
		$this->food = $food;
	}

	public function __toString(){
		return '名字:' . $this->name . '食物是:' . $this->food;
	}

}
	$sheep = new Sheep('懒洋洋', '狼');
	echo $sheep;		// 此时触发toString方法。

3.4 __clone方法

3.4.1 基本介绍

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

3.4.2 举例说明

<?php
class Sheep
{
	public $name;
	protected $food;

	public function __construct($name, $food){
		$this->name = $name;
		$this->food = $food;
	}

	public function __clone(){
		echo 'clone被调用';
	}
}

$sheep1 = new Sheep('多利', '草');
$sheep2 = clone $sheep1;

var_dump($sheep1, $sheep2);		// clone被调用object(Sheep)#1 (2) { ["name"]=> string(6) "多利" ["food":protected]=> string(3) "草" } object(Sheep)#2 (2) { ["name"]=> string(6) "多利" ["food":protected]=> string(3) "草" }

3.5 __call()方法

3.5.1 基本介绍

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

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

3.5.2 举例说明

<?php
class Monk
{
	public $name;
	protected $hobby;

	public function __construct($name, $hobby)
	{
		$this->name = $name;
		$this->hobby = $hobby;
	}

	protected function getSum($num1, $num2){
		return $num1 + $num2;
	}

	public function __call($method_name, $parameters){
		echo '调用了一个不可访问的方法';
	}
}

$monk1 = new Monk('一休', '念经');
$monk1->getSum(100, 200);

4 类的自动加载

4.1 方法1:__autoload()函数

<?php
function __autoload($classname){			// PHP版本7.2.0已经开始不赞成使用这个方法
	require './' . $classname . '.class.php';
}

$cat = new Cat();		// 当实例化一个类时,自动触发自动加载。
$cat->cry();

4.2 方法2:spl_autoload_register()函数

原文地址:https://www.cnblogs.com/falling-maple/p/9260312.html