目录

PHP 类与对象 全解析( 一)

PHP 类与对象 全解析( 二)

PHP 类与对象 全解析(三 )

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
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"
}

---序列化--------反序列化--------------------

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 接口的使用:序列化--------反序列化-

    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
version='1.0'><header/><data><string>member
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 关键字的例子:

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:

/*
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

    class A{  

      $a=new A;
$b=new A;
if($a==$b){
echo "true";
}else{
echo "false";
}
$c=new 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的引用是别名,就是两个不同的变量名字指向相同的内容

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:

    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
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的用法:

1,this是指向对象实例的一个指针,self是对类本身的一个引用,parent是对父类的引用。

1,类的内部使用:如果从类的内部访问不为常量const或者static变量或者方法,那么就必须使用自引用的$this
    2,在构造函数中 指该构造函数创建新对象
    3,引用$this,代表当前的类,解决变量命名冲突和不确定性问题\
   
    --------------------------------

    class Test{
function __call($name,$args){
if($name=='add' && 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)){
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";
例子:
运行该例子输出:
 中国
 我是中国人
 *
 */

    Class Person{
// 定义常量
const COUNTRY = "china";
public function myCountry() {
//内部访问常量
echo "my is ".self::COUNTRY." person<br />";
}
}
// 输出常量
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] )
 *
 */

    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
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
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

    <? 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 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
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.
**/

PHP 类与对象 全解析(三)的更多相关文章

  1. PHP 类与对象 全解析( 二)

    目录 PHP 类与对象 全解析( 一) PHP 类与对象 全解析( 二) PHP 类与对象 全解析(三 ) 7.Static关键字 声明类成员或方法为static,就可以不实例化类而直接访问.不能通过 ...

  2. PHP 类与对象 全解析( 一)

    目录 PHP 类与对象 全解析( 一) PHP 类与对象 全解析( 二) PHP 类与对象 全解析(三 ) 1.类与对象 对象:实际存在该类事物中每个实物的个体.$a =new User(); 实例化 ...

  3. PHP 类与对象 全解析方法

    1.类与对象 对象:实际存在该类事物中每个实物的个体.$a =new User(); 实例化后的$a 引用�php的别名,两个不同的变量名字指向相同的内容 封装: 把对象的属性和方法组织在一个类(逻辑 ...

  4. 你不知道的JavaScript--Item22 Date对象全解析

    本篇主要介绍 Date 日期和时间对象的操作. 1. 介绍 1.1 说明 Date对象,是操作日期和时间的对象.Date对象对日期和时间的操作只能通过方法. 1.2 属性 无: Date对象对日期和时 ...

  5. TCP/IP协议全解析 三次握手与四次挥手[转]

    所谓三次握手(Three-Way Handshake)即建立TCP连接,就是指建立一个TCP连接时,需要客户端和服务端总共发送3个包以确认连接的建立.所谓四次挥手(Four-Way Wavehand) ...

  6. Mybatis源码解析(三) —— Mapper代理类的生成

    Mybatis源码解析(三) -- Mapper代理类的生成   在本系列第一篇文章已经讲述过在Mybatis-Spring项目中,是通过 MapperFactoryBean 的 getObject( ...

  7. 解析Java类和对象的初始化过程

    类的初始化和对象初始化是 JVM 管理的类型生命周期中非常重要的两个环节,Google 了一遍网络,有关类装载机制的文章倒是不少,然而类初始化和对象初始化的文章并不多,特别是从字节码和 JVM 层次来 ...

  8. Celery 源码解析三: Task 对象的实现

    Task 的实现在 Celery 中你会发现有两处,一处位于 celery/app/task.py,这是第一个:第二个位于 celery/task/base.py 中,这是第二个.他们之间是有关系的, ...

  9. PHP7语法知识(三):时间与日期、表单、类与对象、正则表达式、错误异常处理、图像处理

    时间与日期 一.设置时区 1.在配置文件中设置: 2.通过data_default_timezone_set函数在文件中设置: 二.获取当前时间 三.常用时间处理方法 1.格式化时间显示: 2.计算时 ...

随机推荐

  1. WPF添加样式字典Style

    新建Resource Dictionary文件,取名Style: 将常用的样式写入该文件: 在App.xaml中引用该文件: <Application x:Class="Machine ...

  2. sqlServer存储过程与sql语句的区别

    sqlServer   存储过程与sql语句的区别 sql存储过程与sql语句的区别: 从以下几个方面考虑: 1.编写: 存储过程:编写比较难: sql语句:相对简单: 2.性能: 存储过程:高,可移 ...

  3. Handler主线程和子线程相通信

    //创建主线程的handlerprivate Handler handler = new Handler(){ @Override public void handleMessage(Message ...

  4. Android 美学设计基础 <3>

    本期接着对Android的美学设计的分享. 1.3 Light and shadows 光学与阴影 1.3.1 Light 在素材设计的环境中,我们会用虚拟的光来照亮UI界面.主灯光会产生尖锐,有方向 ...

  5. shell 多线程

    不熟悉 io 重定向的童鞋,先学习一下相关知识 http://www.linuxplus.org/kb/io-redirection.html 下面是简单代码 #!/bin/bash tmpfile= ...

  6. storm配置详解

    storm的配置文件在${STORM_HOME}/conf/storm.yaml.下面详细说明storm的配置信息. java.libary.path:storm本身依赖包的路径,有多个路径的时候使用 ...

  7. EL表达式中的11个隐式对象

    EL表达式中定义了11个隐式对象,使用这些隐式对象可以很方便地读取到Cookie.HTTP请求消息头字段.请求参数.Web应用程序中的初始化参数的信息,EL表达式中的隐式对象具体如下: 隐式对象 作用 ...

  8. 初识PHP之php运行流程及原理(一)

    初识PHP一.用脚本命令行运行php(1)打开cmd.exe(winkey+R)(2)找到php.exe(拖进cmd即可)(3)输入命令php.exe -f "文件实际路径"注:运 ...

  9. 3. Decision Tree

    1. 算法流程 一般的,一颗决策树包含一个根结点.若干内部结点和若干叶结点:叶节点对应于决策结果,其他每个结点则对应于一个属性测试结果:每个结点包含的样本集合根据属性测试的结果被划分到子结点中:根结点 ...

  10. vsto之一简介(系列文章为转载)

    该系列文章转载自    http://bbs.51cto.com/thread-1017338-1.html 参考资料 http://www.excelpx.com/thread-184209-1-1 ...