php对象引用及序列化

php类型约束

函数的参数可以指定为对象、数组,注意,即使使用了类型约束,如果使用null作为参数的默认值,那么在调用函数的时候可以使用mull作为实参

例子

<?php

Class MyClass{

    public function test(OtherClass $otherclass){

        echo $otherclass->var;

    }

 

    public function testArray(array $input_array){

        print_r($input_array);

    }

}

 

class OtherClass{

    public $var='hello';

}

 

$myclass=new MyClass();

$otherclass=new OtherClass();

 

$myclass->test('hello');//Argument 1 passed to MyClass::test() must be an instance of OtherClass  参数必须是类otherclass的一个对象

 

$foo=new subClass();

$myclass->test($foo);//Argument 1 passed to MyClass::test() must be an instance of OtherClass  参数必须是类otherclass的实例

 

$myclass->test(null);// Argument 1 passed to MyClass::test() must be an instance of OtherClass, null given 参数不能为空

 

$myclass->test($otherclass);//hello

$myclass->testArray('hello');//Argument 1 passed to MyClass::testArray() must be an array, string given 参数必须是array

$myclass->testArray(array('a','v','d'));// Array ( [0] => a [1] => v [2] => d )

?>

因此:函数调用的参数与定义的参数类型必须一致

另外注意:

1..类型约束允许null值

2.类型约束只支持对象和数组

3.针对接口和抽象类的参数

 

 

<?php

interface fooface

{

    public function foo ();

}

 

class fooclass implements fooface

{

    public function foo ()

    {

        echo ('foo<br>');

    }

}

class barclass implements fooface

{

    public function foo ()

    {

        echo ('bar<br>');

    }

}

class bazclass implements fooface

{

    public function foo ()

    {

        echo ('baz<br>');

    }

}

 

class quuxclass

{

    public function foo ()

    {

        echo ('quux<br>');

    }

}

 

function callfoo (fooface $myClass)

{

    $myClass -> foo ();

}

 

$myfoo = new fooclass;

$mybar = new barclass;

$mybaz = new bazclass;

$myquux = new quuxclass;

 

callfoo ($myfoo);//foo

callfoo ($mybar);//bar

callfoo ($mybaz);//baz

callfoo ($myquux); // Argument 1 passed to callfoo() must implement interface fooface

?>

 

php引用

php引用是别名,就是两个不同的变量名字指向相同的内容,在php5,一个对象变量已经不再保存整个对象的值,只是保存一个标示符来访问真正的对象内容,当对象作为参数传递,最为结果返回,或者赋值给另一个变量,另一个变量跟原来的不是引用的关系,只是他们都保存着同一个标示符的拷贝,这个标示符指向同一个对象的真正内容

<?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";

?>

打印结果是:2 2 2

例子2

<?

class Foo {
  private static $used;
  private $id;
  public function __construct() {
    $id = $used++;
  }
  public function __clone() {
    $id = $used++;
  }
}

$a = new Foo; // $a is a pointer pointing to Foo object 0
$b = $a; // $b is a pointer pointing to Foo object 0, however, $b is a copy of $a
$c = &$a; // $c and $a are now references of a pointer pointing to Foo object 0
$a = new Foo; // $a and $c are now references of a pointer pointing to Foo object 1, $b is still a pointer pointing to Foo object 0
unset($a); // A reference with reference count 1 is automatically converted back to a value. Now $c is a pointer to Foo object 1
$a = &$b; // $a and $b are now references of a pointer pointing to Foo object 0
$a = NULL; // $a and $b now become a reference to NULL. Foo object 0 can be garbage collected now
unset($b); // $b no longer exists and $a is now NULL
$a = clone $c; // $a is now a pointer to Foo object 2, $c remains a pointer to Foo object 1
unset($c); // Foo object 1 can be garbage collected now.
$c = $a; // $c and $a are pointers pointing to Foo object 2
unset($a); // Foo object 2 is still pointed by $c
$a = &$c; // Foo object 2 has 1 pointers pointing to it only, that pointer has 2 references: $a and $c;
const ABC = TRUE;
if(ABC) {
  $a = NULL; // Foo object 2 can be garbage collected now because $a and $c are now a reference to the same NULL value
} else {
  unset($a); // Foo object 2 is still pointed to $c
}

 

?>

 

对象的序列化

在所用的php里面的值都可以使用serialize()来返回一个包含字节流的字符串来表示,unserialize()函数能够重新把字符串变回php原来的值,序列化一个对象将会包存对象的所用的变量,但是不会保存对象方法,值保存类的名字

为了能够unserialze()一个对象,这个对象的类必须已经定义过,如果序列化类A的一个对象,将返回一个跟类A相关,而且包含了对象所有变量值的字符串,如果要想在另一个文件中解序列化一个对象,这个对象的类必须在解序列化之前定义,可以通过包含一个定义该类的文件或使用函数spl_autoload_register()实现

 

<?php
// classa.inc:
  
  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();
?>

当一个应用程序使用函数session_register()来保存对象到会话中时,在每个页面结束的时候这些对象都会自动序列化,而在每个页面开始的时候又自动解序列化。 所以一旦对象被保存在会话中,整个应用程序的页面都能使用这些对象。但是,session_register()这个函数在php5.3.0已经废弃,而且在php6.0.0就不再支持,所以不要依赖这个函数。

在应用程序中序列化对象以便在之后使用,强烈推荐在整个应用程序都包含对象的类的定义。 不然有可能出现在解序列化对象的时候,没有找到该对象的类的定义,从而把没有方法的类__PHP_Incomplete_Class_Name作为该对象的类,导致返回一个没有用的对象。

所以在上面的例子中,当运行session_register("a"),把变量$a放在会话里之后,需要在每个页面都包含文件classa.inc,而不是只有文件page1.phppage2.php。 

posted @ 2012-11-19 08:56  hylaz  阅读(1545)  评论(0编辑  收藏  举报