PHP面向对象的小总结
面向对象特性:
*重用性 (每个模块都可以在项目中重复使用)
*灵活性 (每个模块都很轻松被替换更改的)
*拓展性(在模块上添加新功能是很方便的)
类和对象的关系(类生成对象)
用class 声明一个类,在类里面只能有 成员属性 和 成员方法!!!!不能有其他,在一个脚本中不能有两个同名类,实例化类可以有多个对象
class computer{ public $text = "用关键字new实例化一个类"; public function output(){ echo $this->text; } } $computer = new computer(); $computer->output();
$computer2 = new computer();//可以实例化多个
类的属性和方法
访问控制:
public 公有 都可以访问
private 私有 只有类本身内部可以访问
protected 受保护 继承的子类和类本身内部可以访问,外部访问不了,如: $computer->output();如果output()方法设了protected,则报错。
类里面的方法:
方法里面调用一个属性,需要实例化类才能访问属性,而$this可以理解为是这个类的一个实例
class computer{ public $text = "用$this调用我"; public function output(){ echo $this->text; } }
构造方法与析构方法(实例化时执行和销毁时执行)
构造方法可以传递参数,在实例化时传入
class computer{ function __construct($arg){ echo "我是构造方法,自动执行";
echo $arg;
} }
$conputer = new computer("我是构方法的参数");
析构方法:不能有参数
class computer{ function __destruct(){ echo "我是析构方法,销毁时自动执行"; } } $conputer = new computer(); unset($conputer)//手动释放销毁
类常量
内部访问 self::常量名
外部访问不需要实例化:类名::常量名
class computer{ const yh = 12; const yh2 = self::yh+1; } var_dump (computer::yh2);
$this 和 self 的区别
一个是对象$this 相当于实例化后,可以说除了静态和const常量,基本上其他都可以使用this联络 ;
self则是类本身 self可以访问本类中的静态属性和静态方法,可以访问父类中的静态属性和静态方法。用self时,可以不用实例化的
类的继承
class dad{ function eat(){ echo "我是父类的方法,子类可以继承我的方法"; } } class boy extends dad{ } $boy = new boy(); $boy->eat();
子类也可以覆盖父类的方法
子类没有构造方法时,会调用父类的构造方法,有则调用自己的,
用关键字 parent:: __construct();可以调用父类的构造方法
用final关键字加在类前面就不会被继承;加到方法面前,此方法就不会被重写
命名空间(解决命名冲突问题)
利用文件系统不用目录的原理
被引入的php文件中加入 namespace 目录\子目录;
使用时调用:new 目录\子目录\类名();如 new com\session\computer();
受命名空间影响的有,类(包括抽象类,traits),接口,函数,常量(const和define都是用来声明常量的(它们的区别不详述),但是在命名空间里,define的作用是全局的,而const则作用于当前空间。)
要注意的是,当前脚本文件的第一个命名空间前面不能有任何代码,下面的写法都是错误的:
//例一 //在脚本前面写了一些逻辑代码 <?php $path = "/"; class comment { } namespace article; ?> //例二 //在脚本前面输出了一些字符 <html></html> <?php namespace article; ?>
为什么要说第一个命名空间呢?因为同一脚本文件中可以创建多个命名空间。
<?php
//创建一个名为'article'的命名空间
namespace article;
//此comment属于article空间的元素
class comment { }
//创建一个名为'messageboard'的命名空间
namespace messageboard;
//此comment属于messageboard空间的元素
class comment { }
?>
由于每次调用都要写上路径,很麻烦,所以出现use的用法(use引入必须带类名或者函数名)
在调用时先用use引入,use 目录\子目录\类;还可以起个别名区别 as
use venter\session\computer; use venter\computer as computer2; new computer(); new computer2(); 函数的话记得带上function use function venter\session\computer; computer(); 常量记得带上const use const venter\session\computer; var_dump(computer);
重点:在命名空间里面调用全局的类,函数,常量的区别,
页面a定义了命名空间 namespace venter;引入b页面(全局空间)后,此时想调用b页面的类,必须:
new \venter() 加个\代表全局空间下的
但是调用函数和常量时,就不需要加,因为他会自动寻找,向全局寻找。
类自动加载:
当你实例化一个类时,这个类不存在,就会自动执行我们写的 function __autoload($classname){},在这个自动函数的内部去执行我们想要操作的代码,参数就是我们实例化的类名,因此可以根据参数去引入php文件。
__autoload将被淘汰,使用新的函数 spl_autoload_register();参数可以传函数名或者匿名函数
spl_autoload_register(function($a){ echo $a; } ); new computer(); 或者 function aaa($a){ echo $a; } spl_autoload_register('aaa'); new computer(); 或者类的调用方法 class momo { function aaa($a){ echo $a; } } spl_autoload_register([new momo],'aaa'); new computer();
利用命名空间和自动加载实现项目自动引用
1,文件目录就和命名空间名一样,文件名和类名一样 new models\imooc() 就是在models文件下的imooc.php文件,
2,然后利用spl_autoload_register(function($classname){
include str_replace("\\","/",$classname.".php");
});
这里的作用是models\imooc替换掉models/imooc.php 引入
而imooc.php文件中必须命名 namespace models;
static 静态
当属性和方法被定义为 static 时就变成类的属性和方法,不属于对象的,不需要实例化
class person{ public static $aa ="a"; } echo(person::$aa);
子类用parent::调用父类的静态方法
静态方法不能调用非静态属性
//因为 $this代表实例化对象,而这里是类,不知道 $this 代表哪个对象
后期静态绑定:
class a{ public static function who(){ echo "a类的who方法"; } public static function test(){ self::who(); // static::who(); } } class b extends a{ public static function who(){ echo "b类的who方法"; } } b::test(); 如果是self::who(); 输出的是a类的who方法,说明调用的是a自身,static::who();会根据上下文作处理,类b调用就使用b里面的who()
魔术方法
__set($var,$val) 设置私有属性,当外部调用设置一个私有属性时会自动执行这个方法,
__get($var)获取私有属性,原理是外部调用一个私有属性时会自动执行这个方法
例子:
class test{ private $abc = ""; private $ccc = ""; public function __set($var,$val){ $this->$var = $val; } public function __get($var){ return $this->$var; } } $test = new test(); $test->abc = 'abc'; var_dump($test->abc);
__isset($var)方法,当外部调用isset($test-abc)访问一个不能访问的属性时,就会自动执行
__unset($var),当外部想删除一个私用属性时,会自动执行
__call($func方法名,$arguments参数)当外部调用一个没有定义的方法时,就会调用
__callstatic($meethod,$arg)当调用一个不存在的静态方法时,会自动执行 注意在function 前也要加入 static 因为是静态方法
__invoke($rag)当实例化一个类后,把这个对象变量当成函数调用时,会自动执行
例如:$test = new test();
$test("go....");
__tostring()当要打印一个对象变量时,会执行,比如 echo($test);
对象拷贝:
浅拷贝:是地址传递(对象是浅拷贝)
深拷贝:复制一份,新开辟一块内存(普通变量是深拷贝)
加clone 使对象成为深拷贝,互不影响;
$a = new a();
$b = clone $a;
__clone()当使用clone时,会自动执行
$a = new a();
$b = clone $a; 在a类中会执行__clone()
例子:
class a{ public $obj = null; public function __clone(){ $this->obj = clone $this->obj;//开辟了新空间给克隆的对象 } } class b{ public $sex = 0; } $a = new a(); $a->obj= new b(); $b = clone $a; $b->obj->sex = 1; var_dump($a->obj->sex);
类型约束
class a{ public $obj = null; public function go(){ echo "googogogogo"; } } class b{ public function go(){ echo "bbbbbb"; } } function test(a $a){ $a->go(); } test(new a());//必须是a的实例
trait 关键字
解决单继承问题 配合use 使用
trait a{ public function a(){ echo "aaaaa"; } } trait b{ public function b(){ echo "bbbb"; } } class test{ use a,b; public function c(){ echo "cccc"; } } $test = new test(); $test->a(); $test->b(); $test->c();
接口
可以理解为类的模板 不能直接被实例化
interface person { public function eat(); public function sleep(); } class man implements person{ public function eat(){ echo "chichi吃吃"; } public function sleep(){ echo "shuishushi"; } } $aaa = new man(); $aaa->eat(); //接口继承 两种方法 interface aa { public function eat(); } interface bb { public function sleep(); } interface person extends aa,bb{ //person就直接继承了两种方法 } class man implements person{ public function eat(){ echo "chichi吃吃"; } public function sleep(){ echo "shuishushi"; } } //或者 直接实现两种接口 class man implements aa,bb{ public function eat(){ echo "chichi吃吃"; } public function sleep(){ echo "shuishushi"; } } //接口里面可以利用 const 定义一个常量 interface person { const aa = "bbb"; public function eat(); public function sleep(); } echo person::aa;
抽象类:
内部有自己的执行方法
abstract class person { public function holiday(){ echo '我是抽象类自己的方法' } public function eat(){} public function sleep(){} } class man implements person{ public function eat(){ $this->holiday();//直接调用即可 echo "chichi吃吃"; } public function sleep(){ echo "shuishushi"; } } $aaa = new man(); $aaa->eat();
单例模式:
让一个类只会被实例化一次,节省内存空间
先把构造函数和克隆函数变成私用属性
class test{ private static $_instance = null;//依靠属性存储实例对象判断是否已经实例过 private function __construct(){ // 私有后将不会被外部实例 } private function __clone(){ // 私有后将不会被外部克隆 } public static function getinstance(){ if(!(self::$_instance instanceof self)){ // instanceof判断是否是当前的实例,不是的话就实例化赋值,否则就返回 self::$_instance = new self(); } return self::$_instance; } } $test1 = test::getinstance(); $test2 = test::getinstance(); $test3 = test::getinstance(); var_dump($test1); var_dump($test2); var_dump($test3); // 输出结果object(test)#1 (0) { } object(test)#1 (0) { } object(test)#1 (0) { }
工厂模式:
就是在多处实例化一个类,当这个类名需要改变时,就会导致大量地方需要更改,使用工厂模式避免这种情况发生
class a{ public function a(){ echo 'aaa'; } public function c(){ echo 'ccc'; } public function b(){ echo 'bbb'; } } class cashe{ public static function factory(){ return new a();//当业务逻辑变化时,只需要改此处 } } $cashe = cashe::factory(); $cashe->a();
/*--------------多态的一个应用实例 模拟usb设备的使用------------------*/
//一个usb的接口 interface usb{ function mount();//装载usb的方法 function work();//usb工作的方法 function unmount();//卸载usb的方法 } //定义一个usb设备 u盘 class upan implements usb{//实现usb接口 function mount(){ echo " u盘 装载成功<br/>"; } function work(){ echo "u盘 开始工作<br/>"; } function unmount(){ echo "u盘 卸载成功<br/>"; } } //定义一个usb设备 usb鼠标 class umouse implements usb{//实现usb接口 function mount(){ echo " usb键盘 装载成功<br/>"; } function work(){ echo "usb键盘 开始工作<br/>"; } function unmount(){ echo "usb键盘 卸载成功<br/>"; } } //定义一个电脑类 class computer{ //使用usb设备的方法 function useusb ($usb){//$usb参数表示 使用哪种usb设备 $usb->mount();//调用设备的 装载方法 $usb->work();//调用设备的 工作方法 $usb->unmount();//调用设备的卸载方法 } } //定义一个电脑的使用者的类 class pcuser{ // 安装 usb的方法 function install(){ //首先拿来一台电脑 $pc=new computer; //拿来一些usb设备 $up=new upan;//拿来一个u盘 $um=new umouse;//拿来一个usb鼠标 //把usb设备插入电脑, 使用电脑中使用usb设备的方法 来调用 要插入的设备 $pc->useusb($up);//插入u盘 $pc->useusb($um);//插入usb鼠标 } } //实例化一个电脑用户 $user=new pcuser; $user->install();//安装设备 /*-------------输出内容-------------- u盘 装载成功 u盘 开始工作 u盘 卸载成功 usb键盘 装载成功 usb键盘 开始工作 usb键盘 卸载成功 -----------------------------------*/ ?>
上一篇: day26 - jQuery
下一篇: Python学习之高级特性