SPL--Serializable

Serializable[自定义序列化的接口]

实现此接口的类将不再支持 __sleep() 和 __wakeup()。

作用

为一些高级的序列化场景提供支持。__sleep()和__wakeup()有一些问题,这些问题再SPL中都得到解决。【书上说的,具体的问题之看到了“总结”中的第一个】

总结:(根据看到的例子总结,绝对地不全)

1.魔术方法不能序列化基类的私有变量,SPL可以。

2.SPL可通过子类serialized父类。

3.SPL可以serialize全部的子类变量,子类不需要重写serialize方法。

以例服人:

1.魔术方法不能序列化基类私有变量

<?php

error_reporting( E_ALL );  //开启全部错误提示

class Base {
    private $base;

    public function __construct() {
        $this->base = "base";
    }
}

class Sub extends Base{
    private $sub;

    public function __construct() {
        parent::__construct();  //调用父类的构造方法,为父类中的base赋值
        $this->sub = "sub";
    }

    public function __sleep() {
        return array( "sub", "base" );
    }
}

$instance = new Sub();
$serialized = serialize( $instance );
echo $serialized."\n";
$restored = unserialize( $serialized );

//执行输出
//Notice: serialize(): "base" returned as member variable from __sleep() but does not exist
//O:3:"Sub":2:{s:8:"NULSubNULsub";s:3:"sub";s:4:"base";N;}

使用SPL的Serializable接口就可以解决这个问题

<?php

error_reporting( E_ALL );  //开启全部错误提示

class Base implements Serializable {
    private $base;

    public function __construct() {
        $this->base = "base";
    }

    public function serialize() {
        return serialize( $this->base );
    }

    public function unserialize( $serialized ) {
        $this->base = unserialize( $serialized );
    }

    public function getBase() {
        return $this->base;
    }
}

class Sub extends Base{
    private $sub;

    public function __construct() {
        parent::__construct();  //调用父类的__construct,为父类的base赋值,可通过调用父类的getBase方法获取改值。
        $this->sub = "sub";
    }

    public function serialize() {
        $baseSerialized = parent::serialize();  //注意这个地方
        return serialize( array( $this->sub, $baseSerialized ) );
    }

    public function unserialize( $serialized ) {
        $temp = unserialize( $serialized );
        $this->sub = $temp[0];
        parent::unserialize( $temp[1] );
    }
}

$instance = new Sub();
$serialized = serialize( $instance );
echo $serialized."\n";
$restored = unserialize( $serialized );
echo $restored->getBase();

//执行输出
//C:3:"Sub":43:{a:2:{i:0;s:3:"sub";i:1;s:11:"s:4:"base";";}}
//base

2.通过子类序列化父类

<?php

class Base implements Serializable{
    private $data;

    public function __construct( $data ) {
        $this->data = $data;
    }

    public function getData() {
        return $this->data;
    }

    public function serialize() {
        return serialize( $this->data );
    }

    public function unserialize( $serialize ) {
        $this->data = unserialize( $serialize );
    }
}

class Sub extends Base{
    private $id;
    private $name;

    public function __construct( $id, $name, $data ) {
        parent::__construct( $data );
        $this->id = $id;
        $this->name = $name;
    }

    public function serialize() {
        return serialize(
            array(
                "id" => $this->id,
                "name" => $this->name,
                "parentData" => parent::serialize()  //注意这里
            )
        );
    }

    public function unserialize( $serialize ) {
        $temp = unserialize( $serialize );
        $this->id = $temp["id"];
        $this->name = $temp["name"];
        parent::unserialize( $temp["parentData"] );
    }

    public function getVar() {
        return $this->id."|".$this->name."|".parent::getData();
    }
}

$instance = new Sub( 12, "lee", "hello world" );
$serialized = serialize( $instance );
echo $serialized."\n";
$unserialized = unserialize( $serialized );
echo $unserialized->getVar();

//echo
//C:3:"Sub":86:{a:3:{s:2:"id";i:12;s:4:"name";s:3:"lee";s:10:"parentData";s:19:"s:11:"hello world";";}}
//12|lee|hello world

3.子类不用重写父类serialize方法也能序列化自身的变量,用get_object_vars()函数配合。

<?php

class Pot implements Serializable
{
    protected $_a;
    protected $_b;

    public function serialize() {
        return serialize( get_object_vars( $this ) );
    }
    public function unserialize( $data ) {
        $values = unserialize( $data );
        foreach ( $values as $key=>$value ) {
            $this->$key = $value;
        }
    }
}

//And now one descendant:

class PotId extends Pot
{
    protected $_k;
}

class Pots extends PotId
{
    protected $_l;
}

$pots = new Pots();

echo serialize( $pots );

//echo
//C:4:"Pots":50:{a:4:{s:2:"_l";N;s:2:"_k";N;s:2:"_a";N;s:2:"_b";N;}}
时间: 2024-08-13 08:42:42

SPL--Serializable的相关文章

SPL接口学习总结

迭代器接口描述(接口在C里定义,这只是描述) interface Iterator { public function current(); public function key(); public function next(); public function rewind(); } //迭代器辅助函数 function print_entry($iterator) { print($iterator->current()); return true; } $array = array(1

深入浅出 PHP SPL(PHP 标准库)(转)

一.什么是spl库? SPL是用于解决典型问题(standard problems)的一组接口与类的集合. 此扩展只能在php 5.0以后使用,从PHP 5.3.0 不再被关闭,会一直有效.成为php内核组件一部份. SPL提供了一组标准数据结构. 二.SPL如何使用? 1.构建此扩展不需要其他扩展. 更详细的情况可参考 http://php.net/manual/zh/spl.datastructures.php 双向链表 双链表是一种重要的线性存储结构,对于双链表中的每个节点,不仅仅存储自己

Java中的Serializable接口的作用

转载自:http://blog.csdn.net/shehun11/article/details/40300439 所谓的Serializable,就是java提供的通用数据保存和读取的接口.至于从什么地方读出来和保存到哪里去都被隐藏在函数参数的背后了.这样子,任何类型只要实现了Serializable接口,就可以被保存到文件中,或者作为数据流通过网络发送到别的地方.也可以用管道来传输到系统的其他程序中.这样子极大的简化了类的设计.只要设计一个保存一个读取功能就能解决上面说得所有问题. Obj

序列化与反序列化总结(Serializable和Parcelable)

序列化是指将对象的状态信息转换为可以存储或传输的形式的过程. 在Java中创建的对象,只要没有被回收就可以被复用,但是,创建的这些对象都是存在于JVM的堆内存中,JVM处于运行状态时候,这些对象可以复用, 但是一旦JVM停止,这些对象的状态也就丢失了. 在实际生活中,需要将对象持久化,需要的时候再重新读取出来,通过对象序列化,可以将对象的状态保存为字节数组,需要的时候再将字节数组反序列化为对象. 对象序列化可以很容易的在JVM中的活动对象和字节数组(流)之间转换,广泛用于RMI(远程方法调用)以

面试题:Java中对象序列化接口(Serializable)的意义

Serializable接口是一个里面什么都没有的接口 它的源代码是public interface Serializable{},即什么都没有. 如果一个接口里面什么内容都没有,那么这个接口是一个标识接口,比如,一个学生遇到一个问题,排错排了几天也没解决,此时,她举手了(示意我去帮他解决),然后我过去,帮他解决了,那么这个举手其实就是一个标识,自己不能解决的问题标示我去帮他解决,在Java中的这个Serializable接口是给JVM看的,告诉JVM,我不做这个类的序列化了,你(JVM)给我序

Android Serializable与Parcelable原理与区别

一.序列化.反序列化是什么? (1) 名词解释 对象的序列化 : 把Java对象转换为字节序列并存储至一个储存媒介的过程.对象的反序列化:把字节序列恢复为Java对象的过程. (2) 序列化详细解释 对象的序列化涉及三个点关键点:Java对象.字节序列.存储. 1. Java对象的组成?Java对象包含变量与方法.但是序列与反序列化仅处理Java变量而不处理方法,序列与反序列化仅对数据进行处理. 2. 什么是字符序列?字符序列是两个词,字符是在计算机和电信领域中,字符(Character)是一个

Android中Serializable和Parcelable序列化对象详解

学习内容: 1.序列化的目的 2.Android中序列化的两种方式 3.Parcelable与Serializable的性能比较 4.Android中如何使用Parcelable进行序列化操作 5.Parcelable的工作原理 6.相关实例 1.序列化的目的 (1).永久的保存对象数据(将对象数据保存在文件当中,或者是磁盘中 (2).通过序列化操作将对象数据在网络上进行传输(由于网络传输是以字节流的方式对数据进行传输的.因此序列化的目的是将对象数据转换成字节流的形式) (3).将对象数据在进程

spl之文件处理

spl是php标准库的缩写 spl文件处理类库: SplFileInfo  //是一个类用以获取文件的各种信息SplFileInfo的所有方法如下 方法名            - ---   说明2. getATime( ) : --- Gets last access time of the file3. getBasename( ) : --- Gets the base name of the file4. getCTime( ) : --- 获取文件 inode 修改时间5. getE

Java 序列化Serializable

1.什么是序列化和反序列化Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是一种将这些字节重建成一个对象的过程.   2.什么情况下需要序列化 a)当你想把的内存中的对象保存到一个文件中或者数据库中时候:b)当你想用套接字在网络上传送对象的时候:c)当你想通过RMI传输对象的时候: 3.如何实现序列化 将需要序列化的类实现Serializable接口就可以了,Serializable接口中没有任何方法,可以理解为一个标记,即表明这个

[Serializable]的应用--注册码的生成,加密和验证

1.首先定义注册类RegisterEntity [Serializable] public class RegisterEntity { public string RegisterKey; public bool IsRegistered; public List<int> RegisterOrder; public DateTime RegisterDate; public DateTime ExpireDate; } RegisterKey,注册码(序列号) IsRegistered,是