🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
### 类与对象 1. 类与对象 2. 构造方法、析构方法 3. 成员方法 4. this 5. 垃圾回收器 6. 类的魔术方法 7. 类的自动加载 一、基本用法入门 ~~~ //类 class Cat{ //猫的三个属性 public $name; public $age; public $color; } //创建对象实例 $cat1=new Cat(); $cat1->name='小猫名字'; $cat1->age='5岁'; $cat1->color='黑色'; echo $cat1->name.$cat1->age.$cat1->color; ~~~ ### 规范说明 类名:大写字母开头,驼峰发,动词放前面,名词放后面 ~~~ //使用默认构造函数,效果一样 $对象名=new 类名(); $对象名=new 类名; ~~~ 访问对象属性: ~~~ 对象名->‘属性名’; //对象运算符:-> ~~~ 对象的传递方式 ![](https://box.kancloud.cn/110562d750badb223dc10d0b145295b0_942x402.png) 按引用传递 ![](https://box.kancloud.cn/9dae3803cbe2fd769ba090d7d15fa3b6_869x313.png) ### 成员函数 ~~~ 访问修饰符 function jisuan(){} ~~~ 使用: $person1->speak(); ### 构造函数 创建类的时候,就指定成员属性,完成初始化任务。 无需return即可使用 ~~~ class Cat{ //成员属性 public $name; public function __construct(形参){ //函数体 } } ~~~ this是变化的,指向类的当前实例具体对象,就表示这个对象实例 构造函数和成员方法里面要使用类变量,都得通过类的this指向,不然就是函数里面的局部变量 * 构造函数没有返回值 * 实例化对象的时候,自动调用 * php4中,构造函数和类名一样,php5种使用的是__construct * 如果没有写构造函数,系统默认会生成一个无参数的构造函数 * 一个类只有一个构造函数 *构造函数的参数,一定要在实例化的时候传入参数 ~~~ public function __construct(){} ~~~ ~~~ //类 class Person{ //成员属性 public $name; public $age; //构造函数 public function __construct($myname,$myage){ $this->name=$myname; $this->age=$myage; } } $person1=new Person('猪八戒',200); echo $person1->name; echo $person1->age; ~~~ ### 析构函数 释放对象分配的相关资源。如:释放数据库连接,释放文件的打开 某个对象的所有引用被删除或销毁的时候使用。 什么时候触发析构函数: * 对象运行结束前,也会调用析构函数 * unset()或者Null对象的时候 * 先创建的对象后被销毁,栈的先进后出规则。 ![](https://box.kancloud.cn/a9a44c84c01e4a4f6ff6787cfe10e389_231x234.png) ~~~ function __destruct(){ echo $this->name;.'被析构函数销毁'; } ~~~ ![](https://box.kancloud.cn/af741aacbf32967bd336d467786a7501_768x386.png) #### 析构函数实践: 希望在程序没有结束前,就销毁某个对象实例。及时释放重量级对象 $person=null; 对象销毁,但是数据库连接还能用,在析构函数中,手动销毁数据库连接。 程序退出前,php也将启用垃圾回收机制,销毁对象。 ### this用法 this只能在类的方法里面使用。 ![](https://box.kancloud.cn/e496f282dee62aa2fa29d1cbc3855a72_674x253.png) ### 垃圾回收机制 ### 访问修饰符 public 类的外部和内部任意访问 protected 子类或父类访问,不能在类的外部访问,如果要访问,需要写一个公开的方法来访问 private 在自身的类里面访问。在类的外部使用公开的方法来访问。 ~~~ class Person{ //成员属性 public $name; protected $age; //构造函数 public function __construct($myname,$myage){ $this->name=$myname; $this->age=$myage; } public function getage(){ return $this->age; } } $person1=new Person('猪八戒',200); echo $person1->name; echo $person1->getage(); ~~~ ### 魔术方法 ~~~ __construnct __destruct __call __callStatic __get __set __isset __unset __sleep __wakeup __toString __invoke __set_state __clone ~~~ 魔术方法在满足某种条件下,自动被系统调用 #### __get 读取不可访问的属性的值。如:proteced /private/不存在 #### __set 设置不可访问的属性的值 ~~~ class Person{ //成员属性 public $name; protected $age; //构造函数 public function __construct($myname,$myage){ $this->name=$myname; $this->age=$myage; } function __get($pro_name){ if(isset($this->$pro_name)){ return $this->$pro_name; }else{ echo "属性不存在"; } } function __set($pro_name,$val){ if(isset($this->$pro_name)){ $this->$pro_name=$val; } } } $person1=new Person('猪八戒',200); echo $person1->name; echo "<br>"; echo $person1->age; $person1->age='1000'; echo "<br>"; echo $person1->age; ~~~ ### isset,unset 对不可访问的属性调用isset()或empty()的时候,__isset()会被调用 对不可访问的属性调用unset的时候,__unset会被调用 ~~~ class Person{ //成员属性 public $name; protected $age; //构造函数 public function __construct($myname,$myage){ $this->name=$myname; $this->age=$myage; } function __isset($pro_name){ return isset($this->$pro_name); } function __unset($pro_name){ if(isset($this->$pro_name)){ unset($this->$pro_name); } } } $person1=new Person('猪八戒',200); if(isset($person1->age)){ echo 'age存在'; }else{ echo 'age不存在'; } echo "<pre>"; var_dump($person1); unset($person1->age); var_dump($person1); ~~~ ### __toString() 把类当做字符串输出 ~~~ class Person{ //成员属性 public $name; protected $age; //构造函数 public function __construct($myname,$myage){ $this->name=$myname; $this->age=$myage; } function __toString(){ return "tostring返回信息:".$this->name.'__'.$this->age; } } $person1=new Person('猪八戒',200); echo $person1; ~~~ ### 克隆 clone 克隆魔术函数主要是在单例模型中,防止别人克隆 ~~~ private __clone(){} //克隆不成功 $person2=clone $person1; ~~~ ### __call 调用一个不可访问的方法时候,系统自动调用__call ~~~ class Person{ //成员属性 public $name; protected $age; //构造函数 public function __construct($myname,$myage){ $this->name=$myname; $this->age=$myage; } public function getsum($n1,$n2){ return $n1+$n2; } function __call($method,$args){ return $this->$args[0]($args[1],$args[2]); } } $person1=new Person('猪八戒',200); $res=$person1->showinfo('getsum',3,5); echo $res; ~~~ ### 类的自动加载 __autoload 使用一个没有定义的类,会自动加载autoload函数 ~~~ <?php function __autoload($class_name){ require './$class_name'.'.class.php'; } $cat=new Cat(); ~~~ ![](https://box.kancloud.cn/78bbdbbcf77d6840779e8a4ea89e3a43_509x332.png) ### spl_autoload_register('function');自动加载函数的注册 ![](https://box.kancloud.cn/e6d44a3413744951143ccadf020b2579_563x327.png) ### 静态属性和静态方法 * 静态属性是所有对象共享的变量,如果有修改,也是所有对象的都被修改。 * 无需实例化可直接访问 * * ::范围解析符 * * public static 变量名 * * 方法中访问:self::变量名,类的外部访问,类名::变量名 * 静态变量可以在定义的时候初始化 ~~~ public static $num; function total(){ self::$num; } ~~~ ![](https://box.kancloud.cn/abf959e30c6ee4e4d3c7a7db88579fca_748x299.png) ### self和this的区别 * self是类范畴,指向类 * $this是对象实例(指向对象实例) ### 静态方法: * 访问修饰符 static function 函数名(){} * 调用:self::函数名(); 类的内部,$this->也可以调用,self更规范 * 静态方法中不能调用非静态属性 * 普通成员方法可以访问静态属性 * 如果静态方法是proteced,类的外部不能使用 ![](https://box.kancloud.cn/db40092071cfbabb0562f65db0d26eb7_422x186.png) **没有对象实例的时候调用:** 类名::函数名 **实例化后可以:** 对象名->函数名(); 1. 一般用静态方法操作静态变量 2. 可以在没有实例化的情况下直接调用该方法,(实现单例模式时) **小结:** * 所有对象共享的数据可以定义静态属性 * 静态属性是与类相关的 ### 单例模式 ![](https://box.kancloud.cn/59ec6c121b926d157fd4ef73c681cd48_425x307.png) ![](https://box.kancloud.cn/f4e70ef8a4de0851a15ce12cac9d375b_583x389.png) ![](https://box.kancloud.cn/cbd36f528f8d8f5635009c19dcea2ab3_592x438.png) ### 抽象 抽象是一种研究问题的思路和方法,将一类事物的共同特点提取出来,做成事物的属性和方法。如:银行卡 面向对象3大特征:封装,继承,多态