Le concept de classes et d'objets php

怪我咯
Libérer: 2023-03-11 19:44:01
original
19850 Les gens l'ont consulté

1. Classes et objets

Objet : Un individu qui existe réellement dans chaque objet physique de ce type de chose. $a =new User(); La référence $a
instanciée : alias PHP, deux noms de variables différents pointent vers le même contenu

Encapsulation : Organiser les propriétés et méthodes de l'objet en un seul
Héritage dans une classe (unité logique) : Créer une nouvelle classe basée sur la classe d'origine à des fins de réutilisation du code
Polymorphisme : Autoriser l'affectation du pointeur du type de sous-classe au pointeur de type de classe parent ;
----------------------------------------

2 . Chargement automatique Objet :

Chargement automatique En définissant une fonction de chargement automatique spéciale, cette fonction sera automatiquement appelée lorsqu'une classe non définie dans le script est référencée.

function autoload($class){
  require_once("classes/$class.class.php");
}
Copier après la connexion

Pourquoi devrions-nous utiliser le chargement automatique pour ce fichier ?

3. Surtout lorsqu'il y a beaucoup de fichiers projet, il est impossible d'écrire une longue liste d'exigences au début de chaque fichier...


remplace un
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 recommande l'une des méthodes les plus populaires, y compris le chemin dans le nom du fichier. Par exemple, l'exemple suivant :

$temp = new Main_Super_Class();

view sourceprint?
// Main.class  

function autoload($class_name) {   
     $path = str_replace('_', DIRECTORY_SEPARATOR, $class_name);   
     require_once $path.'.php';   
 }
Copier après la connexion
Tous les traits de soulignement seront remplacés par des séparateurs dans le chemin. Dans l'exemple ci-dessus, Main/Super sera remplacé. être le fichier /Class.php.

Inconvénients :

Dans le processus de codage, vous devez savoir clairement où le fichier de code doit être,

Et parce que le chemin du fichier est codé en dur dans le nom de la classe, si nous devons modifier la structure des dossiers, nous devons modifier manuellement tous les noms de classes.

Si vous êtes dans un environnement de développement et que vous ne vous souciez pas beaucoup de la vitesse, il est très pratique d'utiliser la méthode 'Inclure tout'.

En plaçant tous les fichiers de classe dans un ou plusieurs dossiers spécifiques, puis en les recherchant et en les chargeant via traversal.

Par exemple




Une autre méthode consiste à établir un fichier de configuration associé entre le fichier de classe et son emplacement, par exemple :

<?php   

$arr = array (   
     &#39;Project/Classes&#39;,   
    &#39;Project/Classes/Children&#39;,   
    &#39;Project/Interfaces&#39;  
 );  

 foreach($arr as $dir) {   

    $dir_list = opendir($dir);  

    while ($file = readdir($dir_list)) {   
         $path = $dir.DIRECTORY_SEPARATOR.$file;   
         if(in_array($file, array(&#39;.&#39;, &#39;..&#39;)) || is_dir($path))   
             continue;  
         if (strpos($file, ".class.php"))   
             require_once $path;   
     }   
}   

 ?>
Copier après la connexion

Fichier appelé

view sourceprint?
// configuration.php   

array_of_associations = array(   
    &#39;MainSuperClass&#39; = &#39;C:/Main/Super/Class.php&#39;,   
    &#39;MainPoorClass&#39; = &#39;C:/blablabla/gy.php&#39;  
 );
Copier après la connexion

--------------------------------------------------------- ----- ------

<?php   
    require &#39;autoload_generated.php&#39;;  
    function autoload($className) {   
       global $autoload_list;   
       require_once $autoload_list[$className];   
    }  
      $x = new A();   
?>
Copier après la connexion
3. Constructeurs et destructeurs

Constructeur PHP construct() permet d'exécuter le constructeur avant d'instancier une classe.

Le constructeur est une méthode spéciale dans une classe. Lorsqu'une instance d'une classe est créée à l'aide de l'opérateur new, la méthode constructeur est automatiquement appelée et son nom doit être construct() .

(Un seul constructeur peut être déclaré dans une classe, mais le constructeur ne sera appelé qu'une seule fois à chaque fois qu'un objet est créé. Cette méthode ne peut pas être appelée activement,

elle est donc généralement utilisée pour l'exécution. Certains tâches d'initialisation utiles. Cette méthode n'a pas de valeur de retour. )

Fonction : Utilisée pour initialiser l'objet
constructeur de classe d'exécution de sous-classe parent::construct().

Destructeur : destruct () définition : une fonction membre interne spéciale sans type de retour et sans paramètres. Elle ne peut pas être appelée à volonté et n'est pas surchargée
Elle n'est libérée automatiquement par le système que lorsque la vie de l'objet de classe se termine. constructeur.

La méthode destructeur correspond à la méthode constructeur. La méthode destructeur vous permet d'effectuer certaines opérations ou de compléter certaines fonctions avant de détruire une classe, comme fermer des fichiers, libérer des jeux de résultats, etc.
Le destructeur ne peut prendre aucun paramètre et son nom doit être destruct().

Fonction : nettoyer les conséquences du travail, par exemple, utiliser new pour ouvrir un espace mémoire lors de la création d'un objet et utiliser le destructeur pour libérer les ressources allouées dans le constructeur avant de quitter.


Exemple :


------------------------------ -- ---------------------------------

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

$p1=new Person("ren", 25);
$p1->say();
Copier après la connexion
4. Contrôle d'accès

Oui Le contrôle d'accès aux attributs ou aux méthodes est obtenu en ajoutant les mots-clés public, protected ou private devant eux

Les membres de la classe définis par public sont accessibles de n'importe où les membres de la classe définis par

protected peuvent être accessibles ; accessible de n'importe où Il est accessible par les sous-classes et les classes parents de la classe dans laquelle il se trouve (bien sûr, la classe dans laquelle se trouve le membre est également accessible

les membres de classe définis de manière privée ne sont accessibles que par) ; la classe dans laquelle ils se trouvent.
Contrôle d'accès pour les membres de la classe
Les membres de la classe doivent être définis à l'aide des mots-clés public, protected ou private

Contrôle d'accès aux méthodes
Les méthodes de la classe doivent utiliser le mot-clé public, protected ou private à définir. Si ces mots-clés ne sont pas définis, la méthode sera définie sur le public par défaut.

Exemple :


----------------------------- - ---------------------------------

class MyClass
{
    public $public = &#39;Public&#39;;
    protected $protected = &#39;Protected&#39;;
    private $private = &#39;Private&#39;;

    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
Copier après la connexion
5. Héritage d'objet

Héritage définition : Créer une nouvelle classe basée sur la classe d'origine à des fins de réutilisation du code

------------------------- --- --------

L'écrasement est utilisé lors de l'héritage d'objets

La surcharge est une méthode avec le même nom de méthode mais des paramètres différents dans un seul objet
-------- --- -------------------------------

继承已为大家所熟知的一个程序设计特性,PHP 的对象模型也使用了继承。继承将会影响到类与类,对象与对象之间的关系。

比如,当扩展一个类,子类就会继承父类的所有公有和保护方法。但是子类的方法会覆盖父类的方法。

继承对于功能的设计和抽象是非常有用的,而且对于类似的对象增加新功能就无须重新再写这些公用的功能。

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();
Copier après la connexion

------- --------- ------ --------- -------- -----

6 .范围解析操作符(::)

范围解析操作符(也可称作 Paamayim Nekudotayim)或者更简单地说是一对冒号,可以用于访问静态成员、方法和常量,还可以用于覆盖类中的成员和方法。
当在类的外部访问这些静态成员、方法和常量时,必须使用类的名字。

self 和 parent 这两个特殊的关键字是用于在类的内部对成员或方法进行访问的。
注意:
当一个子类覆盖其父类中的方法时,PHP 不会再执行父类中已被覆盖的方法,直到子类中调用这些方法为止

例子:

<?php
class OtherClass extends MyClass
{
    public static $my_static = &#39;static var&#39;;

    public static function doubleColon() {
        echo parent::CONST_VALUE . "\n";
        echo self::$my_static . "\n";
    }
}

OtherClass::doubleColon();
?>
Copier après la connexion

---------------------------------------------------

7.Static关键字

声明类成员或方法为static,就可以不实例化类而直接访问。不能通过一个对象来访问其中的静态成员(静态方法除外)。

静态成员属于类,不属于任何对象实例,但类的对象实例都能共享。
小结:

在类内部访问静态成员属性或者方法,使用 self::(没有 $ 符号),如:
self:: $country //类内部访问静态成员属性
self:: myCountry()
在子类访问父类静态成员属性或方法,使用 parent::(没有 $ 符号),如:
parent:: $country
parent:: myCountry()
外部访问静态成员属性和方法为 类名/子类名:: ,如:
Person::$country
Person::myCountry()
Student::$country
但静态方法也可以通过普通对象的方式访问

<?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();           // 输出:我是中国人

?>
Copier après la connexion

---------------------------------------------------

8.抽象类 PHP5支持抽象类和抽象方法。

抽象类不能直接被实例化,你必须先继承该抽象类,然后再实例化子类。
抽象类中 至少要包含一个抽象方法。如果类方法被声明为抽象的,那么其中就不能包括具体的功能实现。
继承一个抽象类的时候,子类必须实现抽象类中的所有抽象方法;
另外,这些方法的可见性 必须和抽象类中一样(或者更为宽松)。
如果抽象类中某个抽象方法被声明为protected,那么子类中实现的方法就应该声明为protected或者public,而不 能定义为private。
//抽象方法:abstract protected function getValue();
例子1

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();
Copier après la connexion

例子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(&#39;FOO_&#39;) ."\n";

$class2 = new ConcreteClass2;
$class2->printOut();
echo $class2->prefixValue(&#39;FOO_&#39;) ."\n";
Copier après la connexion

/*
* 抽象类不能直接被实例化,你必须先继承该抽象类,然后再实例化子类。
抽象类中 至少要包含一个抽象方法。如果类方法被声明为抽象的,那么其中就不能包括具体的功能实现。
继承一个抽象类的时候,子类必须实现抽象类中的所有抽象方法;
另外,这些方法的可见性 必须和抽象类中一样(或者更为宽松)。
如果抽象类中某个抽象方法被声明为protected,那么子类中实现的方法就应该声明为protected或者public,而不 能定义为private。
*
*/

class Person {
    public $name;
    public $age;

    function say() {
        echo "my name is:".$this->name."<br />";
    echo "my age is:".$this->age;
    }
}
Copier après la connexion

// 类的继承

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();
Copier après la connexion

---------------------------------------------------------------------

9.接口

接口定义:方法和常量值定义的集合
通过interface来定义一个接口,就像定义一个标准的类一样,但其中定义所有的方法都是空的。

接口的特性:接口中定义的所有方法都必须是public

接口的实现:一个接口可以使用implements操作符,类中必须实现接口中的所有方法,否则会报fatal错误,如果要实现多个接口,可以使用逗号来分隔多个接口的名称。

抽象类和接口的区别

接口是特殊的抽象类,也可以看做是一个模型的规范。接口与抽象类大致区别如下:

1.一个子类如果 implements 一个接口,就必须实现接口中的所有方法(不管是否需要);如果是继承一个抽象类,只需要实现需要的方法即可。
2.如果一个接口中定义的方法名改变了,那么所有实现此接口的子类需要同步更新方法名;而抽象类中如果方法名改变了,其子类对应的方法名将不受影响,只是变成了一个新的方法而已(相对老的方法实现)。
3.抽象类只能单继承,当一个子类需要实现的功能需要继承自多个父类时,就必须使用接口。
实例1:
// 声明一个'iTemplate'接口

interface iTemplate
{
    public function setVariable($name, $var);
    public function getHtml($template);
}
Copier après la connexion

// 实现接口
// 下面的写法是正确的

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(&#39;{&#39; . $name . &#39;}&#39;, $value, $template);
        }
 
        return $template;
    }
}
Copier après la connexion

实例2:
//定义接口

interface User{
     function getDiscount();
     function getUserType();
 }
Copier après la connexion

//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);    //可以是更多其他用户类型
Copier après la connexion

-------------------------------------------------------------

10.重载

定义:一个类中的方法与另一个方法名称相同,但参数不同
什么情况下执行重载? 当调用当前的环境下未被定义的属性或者方法时,或者当调用当前环境下不可见的属性或方法。

提示:
如果父类定义方法时使用了 final 关键字,则不允许被子类方法覆盖。

访问父类被覆盖的方法
可以通过parent:: 符号来访问父类被覆盖的方法或成员属性:
//PHP 重载方法 call()

call()(Method overloading)
为了避免当调用的方法不存在时产生错误,可以使用 call() 方法来避免。该方法在调用的方法不存在时会自动调用,程序仍会继续执行下去。

语法:
// call()方法重载

class Test{
    public function call($name,$args){
     if($name== &#39;null&#39; && count($args)==2 ){
      $type=&#39;num&#39;;
   foreach($args as $key => $val){
       if(!(is_int($val) || is_float($val))){
        $type= &#39;string&#39;;
    }
   }
   $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,&#39;4&#39;);
Copier après la connexion

案例:

class MemberTest {
      
    private $data = array();//被重载的数据保存在此  
    public $declared = 1;/**  重载不能被用在已经定义的属性  */
    private $hidden = 2; /**  只有从类外部访问这个属性时,重载才会发生 */

    public function set($name, $value) {
        echo "Setting &#39;$name&#39; to &#39;$value&#39;\n";
        $this->data[$name] = $value;
    }

    public function get($name) {
        echo "Getting &#39;$name&#39;\n";
        if (array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }

        $trace = debug_backtrace();
        trigger_error(
            &#39;Undefined property via get(): &#39; . $name .
            &#39; in &#39; . $trace[0][&#39;file&#39;] .
            &#39; on line &#39; . $trace[0][&#39;line&#39;],
            E_USER_NOTICE);
        return null;
    }

    /**  PHP 5.1.0之后版本 */
    public function isset($name) {
        echo "Is &#39;$name&#39; set?\n";
        return isset($this->data[$name]);
    }

    /**  PHP 5.1.0之后版本 */
    public function unset($name) {
        echo "Unsetting &#39;$name&#39;\n";
        unset($this->data[$name]);
    }

    /**  非魔术方法  */
    public function getHidden() {
        return $this->hidden;
    }
}


echo "<pre class="brush:php;toolbar:false">\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&#39;s experiment with the private property named &#39;hidden&#39;:\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";
Copier après la connexion

//属性重载:set(),get(),isset(),unset()

class Person{
    private $data =array();
    function set($name,$value){
     $this->data[$name]=$value;
 }
 function get($name){
     return $this->data[$name];
 }
}
Copier après la connexion

-----------------------------------------------------------------------------------

11.对象迭代

PHP5提供了一种迭代(iteration)对象的功能,就像使用数组那样,可以通过foreach 来遍历对象中的属性

class MyClass
{
    public $var1 = &#39;value 1&#39;;
    public $var2 = &#39;value 2&#39;;
    public $var3 = &#39;value 3&#39;;

    protected $protected = &#39;protected var&#39;;
    private   $private   = &#39;private var&#39;;

    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();
Copier après la connexion

---------------------------------------------------------------------------

12.设计模式: 工厂模式和 单例模式,  观察者模式,命令链模式和策略模式

 命令链 模式以松散耦合主题为基础,发送消息、命令和请求,或通过一组处理程序发送任意内容。每个处理程序都会自行判断自己能否处理请求。
如果可以,该请求被处理,进程停止。您可以为系统添加或移除处理程序,而不影响其他处理程序。

工厂模式
定义:工厂模式(Factory)允许你在代码执行时实例化对象。它之所以被称为工厂模式是因为它负责“生产”对象。工厂方法的参数是你要生成的对象对应的类名称。

工厂模式语法:

<?php
class Example
{
    public static function factory($type)
    {
        if (include_once &#39;Drivers/&#39; . $type . &#39;.php&#39;) {
            $classname = &#39;Driver_&#39; . $type;
            return new $classname;
        } else {
            throw new Exception (&#39;Driver not found&#39;);
        }
    }
}
?>
Copier après la connexion

工厂模式案例:

<?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();

?>
Copier après la connexion

单例
定义三要素: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();
Copier après la connexion

这是一种最通常的方式,在一个getInstance方法中返回唯一的类实例。

对这里例子稍加修改,便可以产生一个通用的方法,只要叫道任何你想用到单件的类里,就可以了。

class Teacher{
    function sayHi(){
        return "The teacher smiling and said &#39;Hello &#39;";
    }
    
    static function getInstance(){
        static $instance;
        
        if(!isset($instance)){
            $c = CLASS;
            $instance = new $c;
        }        
        return $instance;
    }
}

echo Teacher::getInstance()->sayHi();
Copier après la connexion

最后一种是提供一个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 &#39;Hello i am a people?&#39;;
    }
}

echo "<br />";
echo singleton::getInstance(&#39;People&#39;)->sayHi();
Copier après la connexion

通过这三种方法,我们可以很容易的应用单件模式,如果能够结合工厂模式,将使我们的编程变得更有条理和效率。
---------------------------------------------------------------------------------------

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); 
?>
Copier après la connexion

---------- 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;}
Copier après la connexion

在这个例子中,首先序列化的对象是 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 = &#39;member value&#39;;
    }
 
    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)));
Copier après la connexion

/*
输出结果为(浏览器中的源代码):

C:7:"MyClass":90:{

member value}
MyClass Object
(
[member] => member value
)
因此如果想用其它语言来实现 PHP 序列化中的 C 标示的话,也需要提供一种这样的机制,让用户自定义类时,
能够自己在反序列化时处理 内容,否则,这些内容就无法被反序列化了。

*/
、、、、
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";
   }
}
Copier après la connexion

---------------------------------------------

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();
Copier après la connexion

------------------------------------------------------------------

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 &#39;FALSE&#39;;
    } else {
        return &#39;TRUE&#39;;
    }
}

function compareObjects(&$o1, &$o2)
{
    echo &#39;o1 == o2 : &#39; . bool2str($o1 == $o2) . "\n";
    echo &#39;o1 != o2 : &#39; . bool2str($o1 != $o2) . "\n";
    echo &#39;o1 === o2 : &#39; . bool2str($o1 === $o2) . "\n";
    echo &#39;o1 !== o2 : &#39; . 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);
Copier après la connexion

-----------------------------------------

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";
Copier après la connexion

-------------------------------------------------------------------------------

对象序列化
序列化对象 - 在会话中存放对象
所有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);
Copier après la connexion

// 把变量$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();
?>
Copier après la connexion

------------------------------------------------------------------------------------------

18.$this关键字

$this 的含义是表示 实例化后的 具体对象!
this的用法:

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

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

class Test{
 function call($name,$args){
  if($name==&#39;add&#39; && count($args)==2){
   $type=&#39;num&#39;;
  }
  foreach ($args as $key=>$val){
   if(!is_int($val) || is_float($val)){
    $type=&#39;string&#39;;
   }
  }
  $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,&#39;4&#39;);
Copier après la connexion

----------------------------------------------
/*
* 常量 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();
Copier après la connexion

--------------------
/*
* 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);
Copier après la connexion

--------------
/*
* 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);
?>
Copier après la connexion

运行结果:

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); 
?>
Copier après la connexion

运行结果:

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(); 
?>
Copier après la connexion

运行结果:

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方法. 
 ?>
Copier après la connexion

程序运行结果:

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(); 
?>
Copier après la connexion

运行结果:

1234 55age ,his sal is 1000 20age , his sal is 800 -20age , his sal is 0 150age , his sal is 0.
**/

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal