OOP面向对象学习笔记(2)---基础实践
一:构造函数与析构函数
- 构造函数:在类被实例化时自动调用的一个函数。主要用来初始化。
- 析构函数:程序运行结束时(或者对象被销毁时)自动调用的最后一个函数。主要用来释放资源等。
- code next...
1 <?php 2 class Test { 3 public function __construct($obj) { 4 echo "hello " . $obj . "<br>"; 5 } 6 public function __destruct() { 7 echo "bye Test<br>"; 8 } 9 } 10 $obj1 = new Test ( "obj1" ); 11 $obj2 = new Test ( "obj2" ); 12 // 在脚本运行结束时自动调用析构函数 13 // 输出:hello obj1 hello obj2 bye Test bye Test 14 // 在对象销毁时,不用等到脚本运行结束,自动调用析构函数 15 $obj3 = new Test ( "obj3" ); 16 $obj3 = null; 17 $obj4 = new Test ( "obj4" ); 18 //输出 hello obj3 bye Test hello obj4 bye Test
二:对象的引用
$james1=&$james 此时$james1和$james同时指向变量的地址。
比喻:$james1和$james是同一个人,只是不同的名字(大名、小名)。
$james1是$james的影子。
三:静态成员
1:为什么要使用静态成员?
为的是让一个类的所有对象都共用这个公共的对象,而不是这个成员属于这个类的某个对象。
举例:所有的NBA球员都有一个总裁lio,现要更换总裁为david,如何实现呢?下面的方法可以。
1 <?php 2 class Player{ 3 public $president="lio"; 4 public function changePresident($pName){ 5 $this->president=$pName; 6 } 7 } 8 $jordan=new Player(); 9 $james=new Player(); 10 $jordan->changePresident("tomacs"); 11 $james->changePresident("david"); 12 echo "jame's president is ".$james->president."<br>"; 13 echo "jordan's president is ".$jordan->president."<br>"; 14 //输出:jame's president is david 15 // jordan's president is tomacs
显然,james和jordan对象可以使用这个方法随意的更改总裁,这样两者就不能实现共有一个总裁了。
我们可以通过静态成员的额方法实现,将方法变成全局的,不属于某一个对象。
1 <?php 2 class Player{ 3 public static $president="lio"; 4 public static function changePresident($pName){ 5 self::$president=$pName; 6 } 7 } 8 $jordan=new Player(); 9 $james=new Player(); 10 Player::changePresident("tomacs"); 11 Player::changePresident("david"); 12 echo "jame's president is ".Player::$president."<br>"; 13 echo "jordan's president is ".Player::$president."<br>"; 14 //输出:jame's president is david 15 // jordan's president is david
四:魔术方法(PHP特有)
1:__toString() 和 __invoke()
1 <?php 2 class Test{ 3 //当对象被当做字符串调用时,会自动执行此方法 4 public function __toString(){ 5 //注意,一定要有return 6 return "hello,this is string!"; 7 } 8 //当对象被当做函数调用时,会自动执行此方法 9 public function __invoke(){ 10 echo "hello,this is invoke!"; 11 } 12 13 } 14 $obj=new Test(); 15 echo $obj; //hello,this is string! 16 $obj(); //hello,this is invoke!
2:__call() 方法重载
1 <?php 2 class Test{ 3 //当类的方法不存在时自动调用此函数 4 public function __call($name,$arg){ 5 //implode()将数组转换为字符串 6 echo "function ". $name ." with param ".implode("---", $arg); 7 } 8 9 } 10 $obj=new Test(); 11 $obj->test(1,2,3);//function test with param 1---2---3
延伸:__callstatic()
1 <?php 2 class Test{ 3 //当类的方法不存在时自动调用此函数 4 public static function __callstatic($name,$arg){ 5 //implode()将数组转换为字符串 6 echo "function ". $name ." with param ".implode("---", $arg); 7 } 8 9 } 10 Test::test(1,2,3);//function test with param 1---2---3
3:__get()、__set()、__isset()、__unset() 属性重载
1 <?php 2 class Test { 3 private $user="lio"; 4 //当对象访问不可访问属性时自动调用此函数 5 public function __get($name) { 6 echo "property ".$name." is denied to access.<br>"; 7 } 8 //当对象为不可赋值属性赋值时,自动调用此方法 9 public function __set($name,$value){ 10 echo "you can not set property ".$name." to value ".$value."<br>"; 11 } 12 //当对不可访问属性使用isset()时,自动调用此方法 13 public function __isset($name){ 14 var_dump(isset($this->$name)); 15 } 16 //当对不可访问属性使用unset()时,自动调用此方法 17 public function __unset($name){ 18 unset($this->$name); 19 } 20 } 21 $obj=new Test(); 22 $obj->user; //property user is denied to access. 23 $obj->user="eric"; //you can not set property user to value eric 24 isset($obj->user); //bool(true) 25 unset($obj->user);
4:__clone()对象克隆
首先明白“克隆”。比如A克隆出B来,则A和B完全相同,但是A和B是两个独立的主体,对象。
举例:现有对象$obj1,如果$obj2=$obj1 ,那么$obj1和$obj2指向同一个对象,不是两个相同的主体。
解决:可以通过$obj2=clone $obj1 解决。那么$obj1和$obj2就是两个独立的主体了。
问题:如果$obj2想对$obj1变异,怎么办呢?
1 <?php 2 class Test { 3 public $user="lio"; 4 //进行变异 5 public function __clone(){ 6 return $this->user="eric"; 7 } 8 } 9 $obj1=new Test(); 10 $obj2=clone $obj1; 11 echo $obj1->user; //lio 12 echo $obj2->user; //eric