高级特性
- 静态方法和属性
声明关键字
static
作用域
静态方法以类为作用域,不能访问累的普通属性,但是允许访问静态属性,类的所有实例都允许访问静态属性(权限允许下)
访问方式
通过‘::’符号访问,当前类访问自己的静态属性和方法通过self关键字,类的实例不允许访问方法内部含有this关键字的静态方法
作用
它在代码中任何地方都能用(可以访问该类)
类的每个实例都可以访问静态属性,利用静态属性来设置值,该值可以被所有类的实例使用
不需要实例化就能访问静态属性和方法,不用为了获取一个简单的功能而实例化对象
- 常量属性
声明关键字
const NAME(常用大写字母命名)
赋值范围
只允许接收基本数据类型的值,不能讲对象指派给常量
访问方式
通过‘::’符号访问,与静态属性一样一般通过类而不是通过类的实例访问常量属性
- 抽象类
声明关键字
abstract
特点
抽象类不能被直接实例化。抽象类只定义(或部分实现)子类需要的方法。子类可以继承它并通过实现其中的抽象方法,使抽象具体化
抽象类也可以创建抽象类的方法和属性(属性不能声明为抽象 Properties cannot be declared abstract)
大多数情况下,抽象类至少包含一个抽象方法,抽象方法abstract声明,不能有方法体
抽象类的子类必须实现抽象类中的所有抽象方法,或者自身也声明为抽象方法,新的方法不能比抽象方法的访问控制更严格,参数个数一样
- 接口
与抽象类的区别
抽象类提供了具体实现的标准,二接口则是纯粹的模板
声明关键字
interface
特点
接口可以包含方法(没有方法体),但是不能有属性的声明(Interfaces may not include member variables)
任何实现接口的类都要实现接口中所定义的所有方法,如果实现接口的类为abstract类,那么如果有些暂时不想实现方法体的方法必须声明为abstract方法
一个类可以同时继承一个父类和实现多个接口
- 延迟静态绑定:static关键字
<?php abstract class DomainObjetc{ private $group; public function __construct(){ $this->group=static::getGroup(); } public static function create(){ return new static();//指向被调用的类而不是包含的类 } static function getGroup(){ return "default"; } } /** * */ class User extends DomainObjetc { } class Documwnt extends DomainObjetc { static function getGroup(){ return "document"; } } class SpreadSheet extends Documwnt { } print_r(User::create());//User Object ( [group:DomainObjetc:private] => default ) print_r(SpreadSheet::create());//SpreadSheet Object ( [group:DomainObjetc:private] => document ) ?>
- Final类和方法final关键字用来终止类的继承或者是方法的复写
- 拦截器
__get($property)访问未定义的属性时被调用
__set($property,$value)给未定义的属性赋值时被调用
__isset($property)对未定义的属性调用isset()时被调用
__call($method,$arg_array)调用未定义的方法时被调用
<?php class test{ public $age=18; public function __get($property){ echo "你访问的未定义属性是:$property"; } public function __set($property,$value){ //$this->$property = $value; echo "你设置的未定义属性是:$property,值是$value"; } public function __isset($property){ echo "你isset判断的未定义属性是:$property"; } public function __unset($property){ echo "你unset的未定义属性是:$property"; } public function __call($method,$arg){ echo "你调用的未定义方法是:$method"; print_r($arg); } } $a = new test(); echo $a->age;//18 $a->name;//你访问的未定义属性是:name $a->name='miake';//你设置的未定义属性是:name,值是miake isset($a->name);//你isset判断的未定义属性是:name unset($a->name);//你unset的未定义属性是:name $a->getAge('123','344','xxxxx');//你调用的未定义方法是:getAge Array ( [0] => 123 [1] => 344 [2] => xxxxx ) ?>
- _clone赋值对象
php4,赋值对象只是简单的将一个变量赋值给另一个变量
php5,对象的clone两个变量指向同一个对象的引用,而没有各自保留一份相同的副本
<?php class acount{ public $balance; function __construct($balance){ $this->balance = $balance; } } /* 浅复制可以保证所有基本数据类型的属性完全被复制 而在复制对象属性时,只复制应用,并不复制应用的对象 */ class person{ private $name; private $age; private $id; public $acount; public function __construct($name,$age,acount $acount) { $this->name = $name; $this->age = $age; $this->acount = $acount; } function setId($id){ $this->id = $id; } function __clone(){//是在复制得到的对象上运行的 $this->id = 0; $this->acount = clone $this->acount; } } $person1 = new person('bob',44,new acount(200)); $person1->setId(343); $person2 = clone $person1; // $person1->acount->balance+=10; print_r($person1->acount->balance);//210 print_r($person2->acount->balance);//200 ?>
- _tostring
<?php class test{ function getName() { return 'hello'; } function getAge(){ return 18; } function __tostring(){ $des = get_class(); $args = get_class_methods($des); foreach ($args as $method) { $des.='method:'.$method.'<br>'; } return $des; } } $a = new test(); print($a); /* testmethod:getName method:getAge method:__tostring */ ?>
- 回调、匿名和闭包
<?php class Product{ public $name; public $price; function __construct($name,$price) { $this->name = $name; $this->price = $price; } } class processing{ private $callback; public function registerCallback($callback){ if(!is_callable($callback)){// throw new Exception("callback not callble", 1); } $this->callback[] = $callback; } public function sale(Product $Product){ echo "{$Product->name}:processing\n"; foreach ($this->callback as $callback){ call_user_func($callback,$Product); } } } class Totailzer{ static function warnAmount($amt){ $count = 0; return function($Product) use($amt,&$count){ $count+=$Product->price; echo " count:$count\n"; if($count>$amt) { echo " hignt price reached:{$count}\n"; } }; } } $processer = new processing(); //回调函数 /*$logger = function($Product){ echo " loging{$Product->name}"; }*/ $processer->registerCallback(Totailzer::warnAmount(8)); $processer->sale(new Product('shoes',6)); $processer->sale(new Product('coffee',6)); ?>