目录 php 类与对象 全解析( 一)
php 类与对象 全解析( 二)
php 类与对象 全解析(三 )
7.static关键字
声明类成员或方法为static,就可以不实例化类而直接访问。不能通过一个对象来访问其中的静态成员(静态方法除外)。
静态成员属于类,不属于任何对象实例,但类的对象实例都能共享。
小结:
在类内部访问静态成员属性或者方法,使用 self::(没有 $ 符号),如:
self:: $country //类内部访问静态成员属性
self:: mycountry()
在子类访问父类静态成员属性或方法,使用 parent::(没有 $ 符号),如:
parent:: $country
parent:: mycountry()
外部访问静态成员属性和方法为 类名/子类名:: ,如:
person::$country
person::mycountry()
student::$country
但静态方法也可以通过普通对象的方式访问
country; // 错误写法 // 访问静态成员方法 person::mycountry(); // 输出:我是中国人 // 静态方法也可通过对象访问: $p1->mycountry(); // 子类中输出成员属性值 echo student::$country.
; // 输出:中国 $t1 = new student(); $t1->study(); // 输出:我是中国人 ?>
---------------------------------------------------
8.抽象类 php5支持抽象类和抽象方法。
抽象类不能直接被实例化,你必须先继承该抽象类,然后再实例化子类。
抽象类中 至少要包含一个抽象方法。如果类方法被声明为抽象的,那么其中就不能包括具体的功能实现。
继承一个抽象类的时候,子类必须实现抽象类中的所有抽象方法;
另外,这些方法的可见性 必须和抽象类中一样(或者更为宽松)。
如果抽象类中某个抽象方法被声明为protected,那么子类中实现的方法就应该声明为protected或者public,而不 能定义为private。
//抽象方法:abstract protected function getvalue();
例子1
abstract class abstractclass{ // 定义抽象方法 abstract protected function getvalue(); // 普通方法 public function printout(){ print $this->getvalue().
; } } class concreteclass extends abstractclass{ protected function getvalue(){ return abstract ;//抽象方法的实现 } } $class1 = new concreteclass; $class1->printout();
例子2
abstract class abstractclass { // 强制要求子类定义这些方法 abstract protected function getvalue(); abstract protected function prefixvalue($prefix); // 普通方法(非抽象方法) public function printout() { print $this->getvalue() . \n; } } class concreteclass1 extends abstractclass { protected function getvalue() { return concreteclass1; } public function prefixvalue($prefix) { return {$prefix}concreteclass1; } } class concreteclass2 extends abstractclass { public function getvalue() { return concreteclass2; } public function prefixvalue($prefix) { return {$prefix}concreteclass2; } } $class1 = new concreteclass1; $class1->printout(); echo $class1->prefixvalue('foo_') .\n; $class2 = new concreteclass2; $class2->printout(); echo $class2->prefixvalue('foo_') .\n;
/*
* 抽象类不能直接被实例化,你必须先继承该抽象类,然后再实例化子类。
抽象类中 至少要包含一个抽象方法。如果类方法被声明为抽象的,那么其中就不能包括具体的功能实现。
继承一个抽象类的时候,子类必须实现抽象类中的所有抽象方法;
另外,这些方法的可见性 必须和抽象类中一样(或者更为宽松)。
如果抽象类中某个抽象方法被声明为protected,那么子类中实现的方法就应该声明为protected或者public,而不 能定义为private。
*
*/
class person { public $name; public $age; function say() { echo my name is:.$this->name.
; echo my age is:.$this->age; } }
// 类的继承
class student extends person { var $school; //学生所在学校的属性 function study() { echo my name is:.$this->name.
; echo my shool is:.$this->school; } } $t1 = new student(); $t1->name = zhangsan; $t1->school = beijindaxue; $t1->study();
---------------------------------------------------------------------
9.接口
接口定义:方法和常量值定义的集合
通过interface来定义一个接口,就像定义一个标准的类一样,但其中定义所有的方法都是空的。
接口的特性:接口中定义的所有方法都必须是public
接口的实现:一个接口可以使用implements操作符,类中必须实现接口中的所有方法,否则会报fatal错误,如果要实现多个接口,可以使用逗号来分隔多个接口的名称。
抽象类和接口的区别
接口是特殊的抽象类,也可以看做是一个模型的规范。接口与抽象类大致区别如下:
1.一个子类如果 implements 一个接口,就必须实现接口中的所有方法(不管是否需要);如果是继承一个抽象类,只需要实现需要的方法即可。
2.如果一个接口中定义的方法名改变了,那么所有实现此接口的子类需要同步更新方法名;而抽象类中如果方法名改变了,其子类对应的方法名将不受影响,只是变成了一个新的方法而已(相对老的方法实现)。
3.抽象类只能单继承,当一个子类需要实现的功能需要继承自多个父类时,就必须使用接口。
实例1:
// 声明一个'itemplate'接口
nterface itemplate { public function setvariable($name, $var); public function gethtml($template); }
// 实现接口
// 下面的写法是正确的
class template implements itemplate { private $vars = array(); public function setvariable($name, $var) { $this->vars[$name] = $var; } public function gethtml($template) { foreach($this->vars as $name => $value) { $template = str_replace('{' . $name . '}', $value, $template); } return $template; } }
实例2:
//定义接口
interface user{ function getdiscount(); function getusertype(); }
//vip用户 接口实现
class vipuser implements user{ // vip 用户折扣系数 private $discount = 0.8; function getdiscount() { return $this->discount; } function getusertype() { return vip user; } } class goods{ var $price = 100; var $vc; //定义 user 接口类型参数,这时并不知道是什么用户 function run(user $vc){ $this->vc = $vc; $discount = $this->vc->getdiscount(); $usertype = $this->vc->getusertype(); echo $usertype.goods price:.$this->price*$discount; } } display ->run(new vipuser); //可以是更多其他用户类型
-------------------------------------------------------------
10.重载
定义:一个类中的方法与另一个方法名称相同,但参数不同
什么情况下执行重载? 当调用当前的环境下未被定义的属性或者方法时,或者当调用当前环境下不可见的属性或方法。
提示:
如果父类定义方法时使用了 final 关键字,则不允许被子类方法覆盖。
访问父类被覆盖的方法
可以通过parent:: 符号来访问父类被覆盖的方法或成员属性:
//php 重载方法 __call()
__call()(method overloading)
为了避免当调用的方法不存在时产生错误,可以使用 __call() 方法来避免。该方法在调用的方法不存在时会自动调用,程序仍会继续执行下去。
语法:
// __call()方法重载
class test{ public function __call($name,$args){ if($name== 'null' && count($args)==2 ){ $type='num'; foreach($args as $key => $val){ if(!(is_int($val) || is_float($val))){ $type= 'string'; } } $method=$name.ucfirst($type); if(method_exists($this,$method),$args){ call_user_func_array(array($this,$method),$args); } } } public addnum($i,$j){ echo $i+$j; } public addstring($i,$j){ echo $i.$j; } } $test =new test(); $test->add(3,4); $test->add(3,'4');
案例:
class membertest { private $data = array();//被重载的数据保存在此 public $declared = 1;/** 重载不能被用在已经定义的属性 */ private $hidden = 2; /** 只有从类外部访问这个属性时,重载才会发生 */ public function __set($name, $value) { echo setting '$name' to '$value'\n; $this->data[$name] = $value; } public function __get($name) { echo getting '$name'\n; if (array_key_exists($name, $this->data)) { return $this->data[$name]; } $trace = debug_backtrace(); trigger_error( 'undefined property via __get(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], e_user_notice); return null; } /** php 5.1.0之后版本 */ public function __isset($name) { echo is '$name' set?\n; return isset($this->data[$name]); } /** php 5.1.0之后版本 */ public function __unset($name) { echo unsetting '$name'\n; unset($this->data[$name]); } /** 非魔术方法 */ public function gethidden() { return $this->hidden; } } echo \n; $obj = new membertest; $obj->a = 1; echo $obj->a . \n\n; var_dump(isset($obj->a)); unset($obj->a); var_dump(isset($obj->a)); echo \n; echo $obj->declared . \n\n; echo let's experiment with the private property named 'hidden':\n; echo privates are visible inside the class, so __get() not used...\n; echo $obj->gethidden() . \n; echo privates not visible outside of class, so __get() is used...\n; echo $obj->hidden . \n;
//属性重载:__set(),__get(),__isset(),__unset()
class person{ private $data =array(); function __set($name,$value){ $this->data[$name]=$value; } function __get($name){ return $this->data[$name]; } }
-----------------------------------------------------------------------------------
11.对象迭代
php5提供了一种迭代(iteration)对象的功能,就像使用数组那样,可以通过foreach 来遍历对象中的属性
class myclass { public $var1 = 'value 1'; public $var2 = 'value 2'; public $var3 = 'value 3'; protected $protected = 'protected var'; private $private = 'private var'; function iteratevisible() { echo myclass::iteratevisible:\n; foreach($this as $key => $value) { print $key => $value\n; } } } $class = new myclass(); foreach($class as $key => $value) { print $key => $value\n; } echo \n; $class->iteratevisible();
---------------------------------------------------------------------------
12.设计模式: 工厂模式和 单例模式, 观察者模式,命令链模式和策略模式
命令链 模式以松散耦合主题为基础,发送消息、命令和请求,或通过一组处理程序发送任意内容。每个处理程序都会自行判断自己能否处理请求。
如果可以,该请求被处理,进程停止。您可以为系统添加或移除处理程序,而不影响其他处理程序。
工厂模式
定义:工厂模式(factory)允许你在代码执行时实例化对象。它之所以被称为工厂模式是因为它负责“生产”对象。工厂方法的参数是你要生成的对象对应的类名称。
工厂模式语法:
工厂模式案例:
getname(); ?>
单例
定义三要素:1,某个类只能有一个实例 2,必须自行创建这个实例 3,必须自行向系统提供这个实例
作用: 1,如果系统中需要有一个类来全局控制某些配置信息,那么使用单例模式可以很方便的实现。
2,使用单例模式,可以避免大量的new操作消耗资源()
3在一个页面请求中,便于调试,因为所有的代码都集中在一个类中(如数据库操作类) 可以在类中设置钩子,输出日志,从而避免到处都是var_dump
单例模式(singleton)用于为一个类生成一个唯一的对象。最常用的地方是数据库连接。 使用单例模式生成一个对象后,该对象可以被其它众多对象所使用。
单件模式是我们在开发中经常用到的一种设计模式,利用php5面向对象的特性,我们可以很容易的构建单件模式的应用,下面是单件模式在php中的几种实现方法:
class stat{ static $instance = null; static function getinstance(){ if(self::$instance == null){ self::$instance = new stat(); } return self::$instance; } private function __construct(){ } private function __clone(){ } function sayhi(){ return the class is saying hi to u ; } } echo stat::getinstance()->sayhi();
这是一种最通常的方式,在一个getinstance方法中返回唯一的类实例。
对这里例子稍加修改,便可以产生一个通用的方法,只要叫道任何你想用到单件的类里,就可以了。
class teacher{ function sayhi(){ return the teacher smiling and said 'hello '; } static function getinstance(){ static $instance; if(!isset($instance)){ $c = __class__; $instance = new $c; } return $instance; } } echo teacher::getinstance()->sayhi();
最后一种是提供一个singleton类,然后通过调用getinstance方法,可以为任何一个类生产出一个实例来。
class singleton{ function getinstance($class){ static $instances = array(); if(!array_key_exists($class,$instances)){ $instances[$class] = &new $class; } $instance = $instances[$class]; return $instance; } } class people{ function sayhi(){ return 'hello i am a people?'; } } echo
; echo singleton::getinstance('people')->sayhi();
通过这三种方法,我们可以很容易的应用单件模式,如果能够结合工厂模式,将使我们的编程变得更有条理和效率。
---------------------------------------------------------------------------------------