郑州有做网站的公司没,中文html5网站欣赏,过年做啥网站致富,百度官网进入1.类与对象 对象#xff1a;实际存在该类事物中每个实物的个体。$a new User(); 实例化后的$a 引用#xff1a;php的别名#xff0c;两个不同的变量名字指向相同的内容 封装: 把对象的属性和方法组织在一个类#xff08;逻辑单元#xff09;里 继承#xff1a;以原有的类…1.类与对象 对象实际存在该类事物中每个实物的个体。$a new User(); 实例化后的$a 引用php的别名两个不同的变量名字指向相同的内容 封装: 把对象的属性和方法组织在一个类逻辑单元里 继承以原有的类为基础创建一个新类从而代码复用的目的 多态允许将子类类型的指针赋值给父类类型的指针。 ------------------------------------- 2.自动加载对象 自动加载通过定义特殊的__autoload函数当引用没有在脚本中定义的类时会自动调用这个函数 [php] view plaincopy print? function __autoload($class){ require_once(classes/$class.class.php); } 为什么要使用__autoload 1首先是不知道这个类文件存放在什么地方 2另外一个就是不知道什么时候需要用到这个文件。 3,特别是项目文件特别多时不可能每个文件都在开始的部分写很长一串的 require … 替代了一 require_once (classes/Books.class.php) ; require_once (classes/Employees.class.php ) ; require_once (classes/Events.class.php) ; require_once (classes/Patrons.class.php) ; zend推荐了一种最流行的办法在文件名中包含路径。例如下面的例子 [php] view plaincopy print? view sourceprint? // Main.class function __autoload($class_name) { $path str_replace(_, DIRECTORY_SEPARATOR, $class_name); require_once $path..php; } $temp new Main_Super_Class(); 所有的下划线都会被替换成路径中的分隔符上例中就会去 Main/Super/Class.php文件。 缺点 是在编码过程中必须明确的知道代码文件应当所处的位置 而且由于将文件路径硬编码在了类名中如果需要修改文件夹的结构时我们必须手工修改所有的类名。 如果是在一个开发环境中并且对于速度不是很在意的话使用Include All’这个方法是非常方便的。 通过将所有类文件放在一个或几个特定文件夹中然后通过遍历的方式查找加载。 例如 [php] view plaincopy print? ?php $arr array ( Project/Classes, Project/Classes/Children, Project/Interfaces ); foreach($arr as $dir) { $dir_list opendir($dir); while ($file readdir($dir_list)) { $path $dir.DIRECTORY_SEPARATOR.$file; if(in_array($file, array(., ..)) || is_dir($path)) continue; if (strpos($file, .class.php)) require_once $path; } } ? 另外一个方法是在类文件和他的位置之间建立关联的配置文件例如 [php] view plaincopy print? view sourceprint? // configuration.php array_of_associations array( MainSuperClass C:/Main/Super/Class.php, MainPoorClass C:/blablabla/gy.php ); 调用的文件 [php] view plaincopy print? ?php require autoload_generated.php; function __autoload($className) { global $autoload_list; require_once $autoload_list[$className]; } $x new A(); ? ------------------------------------------------ 3.构造函数和析构函数 PHP 构造方法 __construct() 允许在实例化一个类之前先执行构造方法。 构造方法是类中的一个特殊方法。当使用 new 操作符创建一个类的实例时构造方法将会自动调用其名称必须是 __construct() 。 (在一个类中只能声明一个构造方法而是只有在每次创建对象的时候都会去调用一次构造方法不能主动的调用这个方法 所以通常用它执行一些有用的初始化任务。该方法无返回值。) 作用 用来创建对象时初始化对象 子类执行分类的构造函数parent::__construct(). 析构函数 __destruct ()定义特殊的内成员函数没有返回类型没有参数不能随意调用也没有重载 只是在类对象生命结束的时候由系统自动调用释放在构造函数中分配的资源。 与构造方法对应的就是析构方法析构方法允许在销毁一个类之前执行的一些操作或完成一些功能比如说关闭文件、释放结果集等。 析构函数不能带有任何参数其名称必须是 __destruct() 。 作用清理了善后工作例如在建立对象时使用new 开辟了一个内存空间应在退出前使用析构函数释放在构造函数中分配的资源。 例子 [php] view plaincopy print? class Person { public $name; public $age; //定义一个构造方法初始化赋值 public function __construct($name,$age) { $this-name$name; $this-age$age; } public function say() { echo my name is :.$this-name.br /; echo my age is :.$this-age; } //析构函数 function __destruct() { echo goodbye :.$this-name; } } $p1new Person(ren, 25); $p1-say(); --------------------------------------------------------------- 4 .访问控制 对属性或方法的访问控制是通过在前面添加关键字 public、protected 或 private 来实现的 public 所定义的类成员可以在任何地方被访问 protected 所定义的类成员则可以被其所在类的子类和父类访问当然该成员所在的类也可以访问 private 定义的类成员则只能被其所在类访问。 对类成员的访问控制 类成员都必须使用关键字public、protected 或 private 进行定义 对方法的访问控制 类中的方法都必须使用关键字public、protected 或 private 进行定义。如果没有设置这些关键字则该方法会被设置成默认的 public。 例子 [php] view plaincopy print? class MyClass { public $public Public; protected $protected Protected; private $private Private; function printHello() { echo $this-public; echo $this-protected; echo $this-private; } } $obj new MyClass(); echo $obj-public; // 这行能被正常执行 echo $obj-protected; // 这行会产生一个致命错误 echo $obj-private; // 这行也会产生一个致命错误 $obj-printHello(); // 输出 Public、Protected 和 Private ------------------------------------------------------------- 5 .对象继承 继承定义以原有的类为基础创建一个新类从而代码复用的目的 -------------------------------------- 覆写是对象继承时用到的 重载是单对象中同方法名不同参数的方法 -------------------------------------- 继承已为大家所熟知的一个程序设计特性PHP 的对象模型也使用了继承。继承将会影响到类与类对象与对象之间的关系。 比如当扩展一个类子类就会继承父类的所有公有和保护方法。但是子类的方法会覆盖父类的方法。 继承对于功能的设计和抽象是非常有用的而且对于类似的对象增加新功能就无须重新再写这些公用的功能。 [php] view plaincopy print? class Person { public $name; public $age; function say() { echo my name is:.$this-name.br /; echo my age is:.$this-age; } } // 类的继承 class Student extends Person { var $school; //学生所在学校的属性 function study() { echo my name is:.$this-name.br /; echo my shool is:.$this-school; } } $t1 new Student(); $t1-name zhangsan; $t1-school beijindaxue; $t1-study(); ------- --------- ------ --------- -------- ----- 6 .范围解析操作符:: 范围解析操作符也可称作 Paamayim Nekudotayim或者更简单地说是一对冒号可以用于访问静态成员、方法和常量还可以用于覆盖类中的成员和方法。 当在类的外部访问这些静态成员、方法和常量时必须使用类的名字。 self 和 parent 这两个特殊的关键字是用于在类的内部对成员或方法进行访问的。 注意 当一个子类覆盖其父类中的方法时PHP 不会再执行父类中已被覆盖的方法直到子类中调用这些方法为止 例子 [php] view plaincopy print? ?php class OtherClass extends MyClass { public static $my_static static var; public static function doubleColon() { echo parent::CONST_VALUE . \n; echo self::$my_static . \n; } } OtherClass::doubleColon(); ? --------------------------------------------------- 7.Static关键字 声明类成员或方法为static就可以不实例化类而直接访问。不能通过一个对象来访问其中的静态成员静态方法除外。 静态成员属于类不属于任何对象实例但类的对象实例都能共享。 小结: 在类内部访问静态成员属性或者方法使用 self::没有 $ 符号如 self:: $country //类内部访问静态成员属性 self:: myCountry() 在子类访问父类静态成员属性或方法使用 parent::没有 $ 符号如 parent:: $country parent:: myCountry() 外部访问静态成员属性和方法为 类名/子类名:: 如 Person::$country Person::myCountry() Student::$country 但静态方法也可以通过普通对象的方式访问 [php] view plaincopy print? ?php Class Person{ // 定义静态成员属性 public static $country 中国; // 定义静态成员方法 public static function myCountry() { // 内部访问静态成员属性 echo 我是.self::$country.人br /; } } class Student extends Person { function study() { echo 我是. parent::$country.人br /; } } // 输出成员属性值 echo Person::$country.br /; // 输出中国 $p1 new Person(); //echo $p1-country; // 错误写法 // 访问静态成员方法 Person::myCountry(); // 输出我是中国人 // 静态方法也可通过对象访问 $p1-myCountry(); // 子类中输出成员属性值 echo Student::$country.br /; // 输出中国 $t1 new Student(); $t1-study(); // 输出我是中国人 ? --------------------------------------------------- 8.抽象类 PHP5支持抽象类和抽象方法。 抽象类不能直接被实例化你必须先继承该抽象类然后再实例化子类。 抽象类中 至少要包含一个抽象方法。如果类方法被声明为抽象的那么其中就不能包括具体的功能实现。 继承一个抽象类的时候子类必须实现抽象类中的所有抽象方法 另外这些方法的可见性 必须和抽象类中一样或者更为宽松。 如果抽象类中某个抽象方法被声明为protected那么子类中实现的方法就应该声明为protected或者public而不 能定义为private。 //抽象方法abstract protected function getValue(); 例子1 [php] view plaincopy print? abstract class AbstractClass{ // 定义抽象方法 abstract protected function getValue(); // 普通方法 public function printOut(){ print $this-getValue().br /; } } class ConcreteClass extends AbstractClass{ protected function getValue(){ return abstract ;//抽象方法的实现 } } $class1 new ConcreteClass; $class1-printOut(); 例子2 [php] view plaincopy print? 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。 * */ [php] view plaincopy print? class Person { public $name; public $age; function say() { echo my name is:.$this-name.br /; echo my age is:.$this-age; } } // 类的继承 [php] view plaincopy print? class Student extends Person { var $school; //学生所在学校的属性 function study() { echo my name is:.$this-name.br /; 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接口 [php] view plaincopy print? interface iTemplate { public function setVariable($name, $var); public function getHtml($template); } // 实现接口 // 下面的写法是正确的 [php] view plaincopy print? 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 //定义接口 [php] view plaincopy print? interface User{ function getDiscount(); function getUserType(); } //VIP用户 接口实现 [php] view plaincopy print? 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()方法重载 [php] view plaincopy print? class Test{ public function __call($name,$args){ if($name null count($args)2 ){ $typenum; 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); 案例 [php] view plaincopy print? 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 pre\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 Lets 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() [php] view plaincopy print? class Person{ private $data array(); function __set($name,$value){ $this-data[$name]$value; } function __get($name){ return $this-data[$name]; } } ----------------------------------------------------------------------------------- 11.对象迭代 PHP5提供了一种迭代iteration对象的功能就像使用数组那样可以通过foreach 来遍历对象中的属性 [php] view plaincopy print? 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允许你在代码执行时实例化对象。它之所以被称为工厂模式是因为它负责“生产”对象。工厂方法的参数是你要生成的对象对应的类名称。 工厂模式语法 [php] view plaincopy print? ?php class Example { public static function factory($type) { if (include_once Drivers/ . $type . .php) { $classname Driver_ . $type; return new $classname; } else { throw new Exception (Driver not found); } } } ? 工厂模式案例 [php] view plaincopy print? ?php interface IUser{ function getName(); } class User implements IUser{ public function __construct($id){} public function getName(){ return haha; } } class UserFactory{ public static function Create($id){ return new User($id); } } $uo UserFactory::Create(1); echo $uo-getName(); ? 单例 定义三要素1某个类只能有一个实例 2必须自行创建这个实例 3必须自行向系统提供这个实例 作用 1如果系统中需要有一个类来全局控制某些配置信息那么使用单例模式可以很方便的实现。 2使用单例模式可以避免大量的new操作消耗资源 3在一个页面请求中便于调试因为所有的代码都集中在一个类中如数据库操作类 可以在类中设置钩子输出日志从而避免到处都是var_dump 单例模式Singleton用于为一个类生成一个唯一的对象。最常用的地方是数据库连接。 使用单例模式生成一个对象后该对象可以被其它众多对象所使用。 单件模式是我们在开发中经常用到的一种设计模式利用PHP5面向对象的特性我们可以很容易的构建单件模式的应用下面是单件模式在PHP中的几种实现方法 [php] view plaincopy print? 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方法中返回唯一的类实例。 对这里例子稍加修改便可以产生一个通用的方法只要叫道任何你想用到单件的类里就可以了。 [php] view plaincopy print? 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方法可以为任何一个类生产出一个实例来。 [php] view plaincopy print? 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 br /; echo singleton::getInstance(People)-sayHi(); 通过这三种方法我们可以很容易的应用单件模式如果能够结合工厂模式将使我们的编程变得更有条理和效率。 --------------------------------------------------------------------------------------- 13.魔术方法 定义PHP把所有以__两个下划线开头的类方法当成魔术方法 __construct, __destruct (参看 构造方法和析构方法), __call, __callStatic, __get, __set, __isset, __unset (参看 重载), __sleep, __wakeup, __toString, __set_state 和 __clone 等方法在PHP中被称为“魔术方法”Magic methods。 你在命名自己的类方法时不能使用这些方法名。 serialize() 作用: 第一. 在序列化之前,关闭对象可能具有的任何数据库连接等. 第二. 指定对象中需要被序列化的成员属性,如果某个属性比较大而不需要储存下来,可以不把它写进__sleep要返回的数组中,这样该属性就不会被序列化 在用serialize序列化对象时会自动调用__sleep方法__sleep方法必须返回一个数组包含需要串行化的属性。 PHP会抛弃其它属性的值 如果没有__sleep方法PHP将保存所有属性包括private属性。 unserialize() 从字节流中创建了一个对象之后,马上检查是否具有__wakeup 的函数的存在。 如果存在__wakeup 立刻被调用。使用 __wakeup 的目的是重建在序列化中可能丢失的任何数据库连接以及处理其它重新初始化的任务。 下面给出一个序列化的代码共serialize.php和unserialize.php两个文件。 [php] view plaincopy print? ?php class User { public $name; public $id; function __construct() { $this-id uniqid(); //give user a unique ID 赋予一个不同的ID } function __sleep() { return(array(name)); //do not serialize this-id 不串行化id } function __wakeup() { $this-id uniqid(); //give user a unique ID } } $u new User; $u-name HAHA; $s serialize($u); //serialize it 串行化 注意不串行化id属性,id的值被抛弃 $u2 unserialize($s); //unserialize it 反串行化 id被重新赋值 //$u and $u2 have different IDs $u和$u2有不同的ID var_dump($u); var_dump($u2); ? ---------- PHP debug ---------- object(User)#1 (2) { [name] string(4) HAHA [id] string(13) 47fa045529f69 } object(User)#2 (2) { [name] string(4) HAHA [id] string(13) 47fa04552a49a } ---序列化--------反序列化-------------------- [php] view plaincopy print? class ClassA { var $int; var $str; var $bool; var $obj; var $pr; } $a new ClassA(); $a-int 1; $a-str Hello; $a-bool false; $a-obj $a; $a-pr $a-str; echo serialize($a); //O:6:ClassA:5:{s:3:int;i:1;s:3:str;s:5:Hello;s:4:bool;b:0;s:3:obj;r:1;s:2:pr;R:3;} 在这个例子中首先序列化的对象是 ClassA 的一个对象那么给它编号为 1接下来要序列化的是这个对象的几个成员第一个被序列化的成员是 int 字段那它的编号就为 2接下来被序列化的成员是 str那它的编号就是 3依此类推到了 obj 成员时它发现该成员已经被序列化了并且编号为 1因此它被序列化时就被序列化成了 r:1; 在接下来被序列化的是 pr 成员它发现该成员实际上是指向 str 成员的一个引用而 str 成员的编号为 3因此pr 就被序列化为 R:3; 了。 //下面举个简单的例子来说明 Serializable 接口的使用序列化--------反序列化- [php] view plaincopy print? class MyClass implements Serializable { public $member; function MyClass() { $this-member member value; } public function serialize() { return wddx_serialize_value($this-member); } public function unserialize($data) { $this-member wddx_deserialize($data); } } $a new MyClass(); echo serialize($a); echo \n; print_r(unserialize(serialize($a))); /* 输出结果为浏览器中的源代码 C:7:MyClass:90:{wddxPacket version1.0header/datastringmember value/string/data/wddxPacket} MyClass Object ( [member] member value ) 因此如果想用其它语言来实现 PHP 序列化中的 C 标示的话也需要提供一种这样的机制让用户自定义类时, 能够自己在反序列化时处理 data 内容否则这些内容就无法被反序列化了。 */ 、、、、 __sleep 和 __wakeup serialize() 函数会检查是否存在一个魔术方法 __sleep.如果存在__sleep()方法会先被调用 然后才执行序列化操作。这个功能可以用于清理对象并返回一个包含对象中所有变量名称的数组。如果该方法不返回任何内容则NULL被序列化导致 一个E_NOTICE错误。 __sleep方法常用于提交未提交的数据或类似的操作。同时如果你有一些很大的对象不需要保存这个功能就很好用。 与之相反unserialize()会检查是否存在一个__wakeup方法。如果存在则会先调用 __wakeup方法预先准备对象数据。 __wakeup经常用在反序列化操作中否则是字符串例如重新建立数据库连接或执行其它初始化操作 ------------------------------------------------------------------------------------------------ 14. Final关键字 如果父类中的方法被声明为final则子类无法覆盖该方法 如果一个类被声明为final则不能被继承。 语法 类使用 final 关键字的例子 [php] view plaincopy print? final class Person { ...... } class BaseClass { public function test() { echo BaseClass::test() called\n; } final public function moreTesting() { echo BaseClass::moreTesting() called\n; } } class ChildClass extends BaseClass { public function moreTesting() { echo ChildClass::moreTesting() called\n; } } --------------------------------------------- 15.对象复制 对象复制可以通过clone关键字来完成如果对象中存在__clone()方法会先被调用。对象中的 __clone()方法不能直接调用。 $copy_of_object clone $object; clone 关键字用于克隆一个完全一样的对象 __clone() __clone() 方法来重写原本的属性和方法。是深复制 如果想在克隆后改变原对象的内容需要在类中添加一个特殊的 __clone() 方法来重写原本的属性和方法。 __clone() 方法只会在对象被克隆的时候自动调用。 clone 关键字用于克隆一个完全一样的对象__clone() 方法来重写原本的属性和方法。 对象克隆 有的时候我们需要在一个项目里面使用两个或多个一样的对象如果使用 new 关键字重新创建对象再赋值上相同的属性这样做比较烦琐而且也容易出错。 PHP 提供了对象克隆功能可以根据一个对象完全克隆出一个一模一样的对象而且克隆以后两个对象互不干扰。 使用关键字 clone 来克隆对象。语法 $object2 clone $object; 例子1 2, __clone() 如果想在克隆后改变原对象的内容需要在类中添加一个特殊的 __clone() 方法来重写原本的属性和方法。 __clone() 方法只会在对象被克隆的时候自动调用。 //例子1 [php] view plaincopy print? /* class Person { private $name; private $age; public function __construct($name, $age) { $this-name$name; $this-age$age; } public function say() { echo my name is :.$this-name.br /; echo my age is :.$this-age; } } $p1 new Person(haha, 20); $p2 clone $p1; $p2-say(); */ class Person { private $name; private $age; function __construct($name, $age) { $this-name $name; $this-age $age; } function say() { echo my name is :.$this-name.br/; echo my age is :.$this-age.br /; } function __clone() { $this-name my is error .$this-name; $this-age 30; } } $p1 new Person(haha, 20); $p1-say(); $p2 clone $p1; $p2-say(); ------------------------------------------------------------------ 16.对象比较 () 如果两个对象的属性和属性值 都相等而且两个对象是同一个类的实例那么这两个对象变量相等。 ()这两个对象变量一定要指向某个类的同一个实例即同一个对象。 实例1 [php] view plaincopy print? class A{ $anew A; $bnew A; if($a$b){ echo true; }else{ echo false; } $cnew A; $d$c; if($c$d){ echo true; }else{ echo false; } } 实例2 function bool2str($bool) { if ($bool false) { return FALSE; } else { return TRUE; } } function compareObjects($o1, $o2) { echo o1 o2 : . bool2str($o1 $o2) . \n; echo o1 ! o2 : . bool2str($o1 ! $o2) . \n; echo o1 o2 : . bool2str($o1 $o2) . \n; echo o1 ! o2 : . bool2str($o1 ! $o2) . \n; } class Flag { public $flag; function Flag($flag true) { $this-flag $flag; } } class OtherFlag { public $flag; function OtherFlag($flag true) { $this-flag $flag; } } $o new Flag(); $p new Flag(); $q $o; $r new OtherFlag(); echo Two instances of the same class\n; compareObjects($o, $p); echo \nTwo references to the same instance\n; compareObjects($o, $q); echo \nInstances of two different classes\n; compareObjects($o, $r); ----------------------------------------- 17.对象和引用 引用php的引用是别名就是两个不同的变量名字指向相同的内容 [php] view plaincopy print? class A { public $foo 1; } $a new A; $b $a; // $a ,$b都是同一个标识符的拷贝 // ($a) ($b) id $b-foo 2; echo $a-foo.\n; $c new A; $d $c; // $c ,$d是引用 // ($c,$d) id $d-foo 2; echo $c-foo.\n; $e new A; function foo($obj) { // ($obj) ($e) id $obj-foo 2; } foo($e); echo $e-foo.\n; ------------------------------------------------------------------------------- 对象序列化 序列化对象 - 在会话中存放对象 所有php里面的值都可以使用函数serialize()来返回一个包含字节流的字符串来表示。 unserialize()函数能够重新把字符串变回php原来的值。 序列化一个对象将会保存对象的所有变量但是不会保存对象的方法只会保存类的名字。 为了能够unserialize()一个对象这个对象的类必须已经定义过。 如果序列化类A的一个对象将会返回一个跟类A相关而且包含了对象所有变量值的字符串。 如果要想在另外一个文件中解序列化一个对象这个对象的类必须在解序列化之前定义可以通过包含一个定义该类的文件或使用函数spl_autoload_register()来实现 实例1 [php] view plaincopy print? class A { public $one 1; public function show_one() { echo $this-one; } } // page1.php: include(classa.inc); $a new A; $s serialize($a); // 把变量$s保存起来以便文件page2.php能够读到 file_put_contents(store, $s); // page2.php: // 要正确了解序列化必须包含下面一个文件 include(classa.inc); $s file_get_contents(store); $a unserialize($s); // 现在可以使用对象$a里面的函数 show_one() $a-show_one(); ------------------------------------ 后期静态绑定 后期绑定“的意思是说static::不再被解析为定义当前方法所在的类而是在实际运行时计算的。也可以称之为”静态绑定“因为它可以用于但不限于静态方法的调用 后期静态绑定的功能用于在继承范围内引用静态调用的类。 self:: 的限制 使用self:: 或者 __CLASS__对当前类的静态引用取决于定义当前方法所在的类 实例1 [php] view plaincopy print? ?php class A { public static function who() { echo __CLASS__; } public static function test() { self::who(); } } class B extends A { public static function who() { echo __CLASS__; } } B::test(); ? ------------------------------------------------------------------------------------------ 18.$this关键字 $this 的含义是表示 实例化后的 具体对象 this的用法 1this是指向对象实例的一个指针self是对类本身的一个引用parent是对父类的引用。 1类的内部使用如果从类的内部访问不为常量const或者static变量或者方法,那么就必须使用自引用的$this 2在构造函数中 指该构造函数创建新对象 3引用$this代表当前的类解决变量命名冲突和不确定性问题\ -------------------------------- [php] view plaincopy print? class Test{ function __call($name,$args){ if($nameadd count($args)2){ $typenum; } foreach ($args as $key$val){ if(!is_int($val) || is_float($val)){ $typestring; } } $method$name.ucfirst($type); if(method_exists($this,$method)){ call_user_func_array(array($this,$method),$args); } } function addNum(){ echo $i$j; } function addString(){ echo $i.$j; } } $test new Test(); $test-add(3,5); $test-add(4,4); ---------------------------------------------- /* * 常量 const 在类里面定义常量用 const 关键字而不是通常的 define() 函数。 语法 const constant value; 例子 运行该例子输出 中国 我是中国人 * */ [php] view plaincopy print? Class Person{ // 定义常量 const COUNTRY china; public function myCountry() { //内部访问常量 echo my is .self::COUNTRY. personbr /; } } // 输出常量 echo Person::COUNTRY.br /; // 访问方法 $p1 new Person(); $p1 - myCountry(); Person::myCountry(); -------------------- /* * PHP 对象的存储与传输序列化 serialize 对象 对象的存储与传输 在实际项目应用中有些任务在一两个页面是无法完成的由于变量到脚本执行完毕就释放我们本页所生成的对象想在其它页面使用时便碰到了麻烦。 如果需要将对象及其方法传递到我们想使用对象的页面比较简单可行的办法是将对象序列化后存储起来或直接传输给需要的页面另一种办法是将对象注册为 session 变量。 序列化对象 对象序列化就是将对象转换成可以存储的字节流。当我们需要把一个对象在网络中传输时或者要把对象写入文件或是数据库时就需要将对象进行序列化。 序列化完整过程包括两个步骤一个是序列化就是把对象转化为二进制的字符串serialize() 函数用于序列化一个对象另一个是反序列化就是把对象被序列转化的二进制字符串再转化为对象unserialize() 函数来反序列化一个被序列化的对象。这样整个过程下来对象内的类型结构及数据都是完整的。 语法 string serialize( mixed value ) mixed unserialize( string str [, string callback] ) * */ [php] view plaincopy print? class Person { private $name; private $age; function __construct($name, $age) { $this-name $name; $this-age $age; } function say() { echo my name is .$this-name.br /; echo my age is .$this-age; } } $p1 new Person(haha, 20); $p1_string serialize($p1); //将对象序列化后写入文件 $fh fopen(p1.text, w); fwrite($fh, $p1_string); fclose($fh); -------------- ?php /* * PHP面向对象之this 关键字 1,PHP5中为解决变量的命名冲突和不确定性问题引入关键字“$this”代表其所在当前对象。 2,$this在构造函数中指该构造函数所创建的新对象。 3,在类中使用当前对象的属性和方法必须使用$this-取值。方法内的局部变量不属于对象不使用$this关键字取值。 局部变量和全局变量与 $this 关键字 4,使用当前对象的属性必须使用$this关键字。 局部变量的只在当前对象的方法内有效所以直接使用。 注意局部变量和属性可以同名但用法不一样。在使用中要尽量避免这样使用以免混淆。 1234567891011121314 !-- 验证属性和局部变量使用方法的类 -- [php] view plaincopy print? ?php class A{ private $a 99; //这里写一个打印参数的方法. public function printInt($a){ echo 这里的 \$a 是传递的参数 $a ; echo br; echo 这里的 \$this-a 是属性 $this-a; } } $a new A(); // 这里的$a 可不是类中的任何一个变量了. $a-printInt(88); ? 运行结果 12 这里的 $a 是传递的参数 88 这里的 $this-a 是属性 99 用$this调用对象中的其它方法 1234567891011121314151617 !--写一个类,让他自动完成最大值的换算.-- [php] view plaincopy print? ?php class Math{ //两个数值比较大小. public function Max($a,$b){ return $a$b?$a:$b; } //三个数值比较大小. public function Max3($a,$b,$c){ //调用类中的其它方法. $a $this-Max($a,$b); return $this-Max($a,$c); } } $math new Math(); echo 最大值是 .$math-Max3(99,100,88); ? 运行结果 1 最大值是 100 使用$this调用构造函数 调用构造函数和析构函数的方法一致。 12345678910111213141516 [php] view plaincopy print? ? class A{ private $a 0; public function __construct(){ $this-a $this-a 1 ; } public function doSomeThing(){ $this-__construct(); return $this-a; } } $a new A(); // 这里的$a 可不是类中的任何一个变量了. echo 现在 \$a 的值是 . $a-doSomeThing(); ? 运行结果 1 现在 $a 的值是2 $this 到底指的什么 $this 就是指当前对象我们甚至可以返回这个对象使用 $this 12345678910111213 [php] view plaincopy print? ?php class A{ public function getASelf(){ return $this; } public function __toString(){ return 这是类A的实例.; } } $a new A(); // 创建A的实例; $b $a-getASelf(); //调用方法返回当前实例. echo $a; //打印对象会调用它的__toString方法. ? 程序运行结果 1 这是类A的实例. 通过 $this 传递对象 在这个例子中,我们写一个根据不同的年龄发不同工资的类. 我们设置处理年龄和工资的业务模型为一个独立的类. 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455 [php] view plaincopy print? ?php class User{ private $age ; private $sal ; private $payoff ; //声明全局属性. //构造函数,中创建Payoff的对象. public function __construct(){ $this-payoff new Payoff(); } public function getAge(){ return $this-age; } public function setAge($age){ $this-age $age; } // 获得工资. public function getSal(){ $this-sal $this-payoff-figure($this); return $this-sal; } } //这是对应工资与年龄关系的类. class Payoff{ public function figure($a){ $sal 0; $age $a-getAge(); if($age 80 || $age 16 ){ $sal 0; }elseif ($age 50){ $sal 1000; }else{ $sal 800; } return $sal; } } //实例化User $user new User(); $user-setAge(55); echo $user-getAge().age ,his sal is . $user-getSal(); echo br; $user-setAge(20); echo $user-getAge().age , his sal is . $user-getSal(); echo br; $user-setAge(-20); echo $user-getAge().age , his sal is . $user-getSal(); echo br; $user-setAge(150); echo $user-getAge().age , his sal is . $user-getSal(); ? 运行结果: 1234 55age ,his sal is 1000 20age , his sal is 800 -20age , his sal is 0 150age , his sal is 0. **/转载于:https://www.cnblogs.com/AnonymouL/p/5498430.html