我爱编程

PHP 学习笔记(三)

2018-04-10  本文已影响0人  _1633_

参考资料:PHP5 权威编程


笔记开始

PHP 中的类和对象

            对象:万物皆对象;

            类: 任何对象,都可以人为规定为某种类型(类别)。

PHP中的对象

            类是描述一类事物的一个总称,是具有相同特征的该类事物的一个通用名称。

            对象是一个明确的具体的物体,是某个类中的一个实物(类就是一个抽象的概念)。对象一定隶属于某个类--------有类才有对象,先有类再有对象

            属性和方法

            在面相对象过程中

            属性就是原来的变量,写在一个类中,原来的变量就称为属性(类的变量成员叫属性);

            方法就是原来的函数,写在一个类中,原来的函数就称为方法。

属性和方法

            对象的创建

4种创建方法

            对象的传值方式

              对象的存储模式(结构):

                        $变量 ---->  对象标识符/编号(#1) ----->  #1对象数据本身

                        并且:该变量中存储的实际是该对象的标识符/编号。这个标识符或编号有能力去“指向对象”;

值传递 引用传递

                    对象中的 值传递引用传递 结果一样, 但是过程却不相同

                    值传递过程

值传递

                    引用传递

引用传递 引用传递

        类中成员

                类中成员分为3大类

                    属性:1 普通属性  2 静态属性

                    方法: 1 普通方法 2 静态方法 3 构造方法 4 析构方法

                    常量

                类常量

                    定义形式 

                        class 类名{

                            const 常量名 ;     // 不能使用define

                        }

                    使用形式

                        常量的使用,是通过类名,并使用范围解析符(::)来取用的;

                        类名::常量名;

常量使用形式

                普通属性(实例属性)

                    定义形式

                        class 类名{

                            var $属性名 = 初始值;

                            var $属性名;

                            // 另一种形式

                            public $属性名 = 初始值;

                            public $属性名;

                        }

                    使用形式

                        $对象->属性名;(没有$符号!!)


                静态属性

                    静态属性,本质上也是“变量”,但其有一个特点就是:该变量只隶属于“类”,即:

                    一个类中的一个静态属性,就只有“一份数据”;

                    一个类中的一个实例属性,就可以有“多份数据”——每创建一个对象出来,就会有一份数据;

                    定义形式

                        class  类名{

                            static $属性名 =  初始值;

                            static $属性名;

                        }

                    使用形式

                        使用类名和范围解析符(::)来对静态属性进行操作:

                        类名::$静态属性名;    //注意:属性名带$符号!!!!!!

静态属性只有一份数据

                1,实例属性,是每个对象都可以不一样的数据,也是每个对象都“独自拥有”的数据;

                2,静态属性,他不属于任何一个对象,而只属于该类本身,也可以理解为为所有对象所共有的数据;

                普通方法(实例方法)

                     定义形式

                        class  类名{

                            function 方法名($形参1,$x形参2....){

                                // code.......

                            }

                        }

                    调用形式

                    $对象名->方法名(实参1,实参2,....);

                静态方法

                       一个类中定义的方法,只隶属于这个类本身,而不是隶属于这个类的对象。

                       定义形式

                            class  类名{

                                 static function 方法名($形参1,$x形参2....){

                                    // code.......

                                    }

                            }

                        调用形式

                        类名::方法名(实参1,实参2,....);

静态方法

                self关键字:用在方法中,表示该方法所在的类

                static关键字代替self关键字的位置,除了具有self作用外,还具有更灵活的作用,那就是所谓“后期静态绑定”。

                构造方法(__construct)

                构造方法是一个类在进行实例化(new一个对象出来)的时候,会 首先自动调用 的方法。主要的目的是为了在new一个对象的时候,给该对象设置一些“初始值”(初始化工作);构造方法的参数没有规定,通常是根据实际的需要来定义,目的是为了对象属性数据的初始化。

  构造方法(__construct)  


                析构方法(__destruct)

                析构方法是一个对象被销毁的时候被 自动调用 的方法,自己无法调用。

                析构方法  不能带参数(形参),只能是public的。但方法中也可以使用$this这个词,代表“当前对象”。

                如果一个类中定义了析构方法,则销毁对象时就会调用该方法。

                如果一个类中没有定义析构方法,则销毁对象时就会调用其父类的析构方法(如果有)

 析构方法(__destruct)

                   

       对象在哪些情况下会被销毁?

                1,如果程序结束,所有变量都会被销毁,自然,变量所代表的对象也会被销毁;

程序结束 对象销毁

                对象销毁的顺序,默认情况下,跟其创建的顺序相反

                2,当一个对象没有任何变量“指向”它的时候,即使程序还没有结束,也会被销毁;

一个对象没有任何变量“指向”它

                    此时,$obj1 断开了指向 ,但是程序还没也结束,此时,也会销毁对象。此时执行析构方法。

                3,当变量赋值为标量,不能再指向对象,对象就会被销毁。

变量赋值为标量

          类的继承

                    将一个类A中的特性信息,传递到另一个类B中,此时就称为:

                    B继承A

                    A派生出B;

                    基本语法:extends

extends

                    说明

                        父类/子类:已有类为父类,新建类为子类。父类又可以称为“基类”,上级类,子类又称为派生类,下级类,

                        单继承:一个类只能从一个上级类继承其特性信息。PHP和大多数面向对象的语言都是单继承模式。C++是多继承。

                        扩展:在子类中再来定义自己的一些新的特有的特性信息(属性,方法和常量)。没有扩展,继承也就没有意义了。

          访问控制修饰符    

                        public:公告的,在所有位置都可以访问;

                        protected:受保护的,只能在该类内部和该类的子类或者父类中访问和使用;

                        private:私有的,只能在该类内部访问。

                        形式    

                            class 类名{

                                访问控制修饰符  属性或者方法

                            }

                        作用:用来 限制 其说修饰的成员的 可访问性,即用

                        对象->实例属性和方法  或者 类::静态属性和静态方法   的合理性。

                    访问控制修饰符,需要结合使用该语法形式的所在位置,才能确定是否可访问。

                   3个访问位置:类的内部,  继承类的内部,类的外部  

访问的权限

                    总结:

                    1,public修饰的成员,哪里都能访问

                    2,类的内部,可以访问任何级别的成员

                    3,public具有最宽泛的可访问性;private具有最狭小的可访问性;protecte则居中;

访问控制修饰符    外部 访问控制修饰符    内部 访问控制修饰符    继承类内部  

          parent关键词

                    paren在面向对象语法中,代表“父类”。本质上就是代表父类这个“类”,而不是父类的“对象”;

                    使用方式为:

                      parent::属性或方法; //通常是静态属性或静态方法,但有时候可能是实例属性或实例方法;

  parent关键词

                    三个关键字对比

三个关键字对比

                   构造方法  析构方法 在父类和子类中的运用

                    1,如果一个类 有构造方法,则实例化这个类的时候,就不会调用父类的构造方法(如果有);

                    2,如果一个类没有构造方法,则实例化这个类的时候,就会自动调用父类的构造方法(如果有);                

                    3,如果一个类 有析构方法,则销毁这个类的时候,就不会调用父类的析构方法(如果有);

                    4,如果一个类没有析构方法,则销毁这个类的时候,就会自动调用父类的析构方法(如果有);

                    5,如果一个类中有构造方法或析构方法,则就可以去“手动”调用父类的同类方法(如果有);

                手动调用的语法形式总是这样:

                parent::构造方法或析构方法()

  parent::构造方法或析构方法()


       覆盖(override)

                覆盖,又叫“重写”,将一个类从父类中继承过来的属性和方法“重新定义”——此时相当于子类不用父类的该属性或方法,而是重新定义。

覆盖

            访问控制权限:

                    子类覆盖的属性或方法的访问控制权限,不能“低于”父类的被覆盖的属性或方法的访问控制权限:

                具体来说:

                父类:public 子类:只能是public

                父类:protected 子类:可以是protected和public

                父类:private 子类:不能覆盖!——既父类的私有成员,不存在被子类覆盖的可能。

                方法的参数形式:

                子类覆盖父类的同名方法的时候,参数要求跟父类保持一致;

                特例:

                构造方法重写的时候参数可以不一致

                小注意:

                虽然父类的私有属性不能被覆盖,但子类却可以定义自己的跟父类同名的属性;

                虽然父类的私有方法不能被覆盖,但子类也不能定义自己的同名方法;


        最终类

            最终类,其实就是一种特殊要求的类:要求该类不允许往下继承下去。

            形式:

                final  class类名{

                //类的成员定义。。。跟一般类的定义一样!

                }

        最终方法

            最终方法,就是一个不允许下级类去覆盖的方法!!

            形式:

                class类名{

                    final  function方法名(形参列表...){ 。。。。。 }

                }

       设计模式

            设计模式就是解决某个问题的一般性代码的经验性总结。

                        工厂模式

                            所谓工厂模式,就是这样一个类(就是所谓的工厂类):它可以根据“传递”给他的类名,而去生产出对应的类的对象。

                           工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式

工厂模式

                        

                        单例模式

                        通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。

单例模式

      抽象类和抽象方法

                抽象类:一个不能实例化的类

                    形式:abstract   class  类名{    }        

                抽象方法:是一个只有方法头,没有方法体的方法定义形式

                    形式:abstract function 方法名();    //注意,这里必须有分号;

                抽象类  和  抽象方法  注意事项

                1 一个抽象方法必须在抽象类中,抽象类中不一定有抽象方法(不常见);

                2 被定义为抽象的方法只是声明了其调用方式(参数),不能定义其具体的功能实现。 抽象方法是为了规定下级类中必须去完成对抽象方法的详细描述;

                3子类实现父类的抽象方法的时候,其形参也应该跟父类保持一致,其访问权限也不能更小;——其原因其实这是“重写现象”,自然应该遵循重写的要求;

抽象类和抽象方法

        重载技术 

                重载的基本概念

                        PHP所提供的重载(overloading)是指动态地创建类属性和方法。简单来说,当对一个对象或类使用其未定义的属性或方法的时候,其中的一些“处理机制”。

                        我们是通过魔术方法(magic methods)来实现的。 

重载

                属性重载

                    就是对一个对象的不存在的属性进行使用的时候,这个类中预先设定好的应对办法(处理机制);

                    属性,本质,就是变量,其只有4个操作:

                    取值:当对一个对象的不存在的属性进行“取值”的时候,就会自动调用内部方法:__GET()

                    __GET($属性名)

                    该方法可以带一个形参,表示这个要对之取值的不存在的属性名(字符串);

 __GET

                     赋值:当对一个对象的不存在的属性进行“赋值”的时候,就会自动调用内部方法:__SET()

                    __SET($属性名,值)

                     它有2个形参,分别代表要对不存在的属性进行赋值的时候的“属性名”和“属性值”;

__SET($属性名,值)

                    判断(isset):当对一个对象的不存在的属性进行isset()判断的时候,就会自动调用内部方法:__isset()

                    __isset(属性名)

             __isset(属性名) 

                    销毁(unset):当对一个对象的不存在的属性进行unset()销毁的时候,就会自动调用内部方法:__unset()

                __unset(属性名)

  __unset(属性名)

                方法重载

                当对一个对象的不存在的实例方法进行“调用”的时候,会自动调用类中的__call()这个魔术方法;

                当对一个类的不存在的静态方法进行“调用”的时候,会自动调用类中的__callstatic()这个静态魔术方法

                __call($method_name , $argument )

                $method_name 表示要调用的不存在的方法名

                $argument  表示要调用的不存在的方法所使用的实参数据,是一个数组

   __call($method_name , $argument )  

        接口

                使用接口(interface),可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容

                接口是通过interface关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的

                接口中定义的所有方法都必须是公有,这是接口的特性。

                接口里面只能放 “抽象方法” 和 “常量”。

                形式:

                    interface 接口名{

                        常量1;

                        常量2;    

                        .........

                        抽象方法1;

                        抽象方法2;

                    }

                        接口常量的使用形式为:接口名称::常量名称;

                        接口中的抽象方法,不要使用abstract修饰,也不需要使用访问控制修饰符,因为其天然就是public。

接口

                        接口的作用

                        PHP是单继承,但是运用中往往要运用到 多继承,接口就是对没有多继承的类之间关系的一个补充。

                        接口可以实现“多继承”——但此时不称为继承而已,而是称为“实现”;

                            即: 接口1  -->>类1;   称为:类1实现了接口1;

                            其本质,其实就是类1中,有了接口1中“特征信息”

                        使用形式:

                        class 类名 implements接口1,接口2.....{

                        }

接口作用

       

       类的自动加载

                    当某行代码需要一个类的时候,php的内部机制可以做到“自动加载该类文件”,以满足该行需要一个类的这种需求。  

                    什么时候需要一个类

                    1 new一个对象的时候;

                    2 使用一个类的静态方法的时候;

                    3 定义一个类(B)并以另外一个类(A)作为父类的时候。

自动加载函数    

            使用条件

                1, 当需要一个类的时候,就会自动调用某个函数(默认是__autoload),并传入所需要的类的名字;

                2,一个类应该保存到一个独立的“类文件中”:即其中只有该类的定义,没有别的代码

                3,习惯上,类文件的命名要有一定的“规则”,通常是:类名.class.php;

                4,在自动加载函数中,形参为需要加载的类名,所以要拼凑好正确的路径。

        自定义自动加载函数

            __autoload 函数是系统定义的自动加载函数,在需要时,我们可以自定义 自动加载函数。

           形式

           spl_autoload_register(“函数1”); //声明“函数1”作为自动加载函数;

           spl_autoload_register(“函数2”); //声明“函数2”也作为自动加载函数;

            .........

            定义(与__autoload一样)

            function 函数1( $class_name ){

              //.......

            }

            function函数2( $class_name ){

                //.......

            }

自定义自动加载函数


        对象的复制(克隆)

            对象的克隆,就是用于将一个对象“制作”双份,类似之前普通数据的“值传递”;   

              定义

                $obj2  =  clone  $obj1; //这样,就有一个跟$obj1完全一样的新的对象。

   对象的复制(克隆)

            __clone 魔术方法

            使用 clone  会克隆出一个跟当前对象一样的新的对象,并且会调用该类中的魔术方法:__clone ,只要 该类中有该方法。    

            在单例模式中,应该禁止对该单例的克隆,所有要在该类中禁止__clone 魔术方法,做法就是私有化__clone

            第4步私有化这个克隆的魔术方法

            private function __clone {//不用写代码}


        对象的遍历     

        对象的遍历,跟数组的遍历,一样!只能遍历出对象的“实例属性数据”。

        foreach($对象名  as  $key=>$value){

                //处理$key  $value

         }

        说明:1 $key 是对象的属性名,$value 是其对应的值;

                   2 能变量出来的属性,根据访问控制权限,只能是在该范围中的“可访问属性”;

对象的遍历

        PHP内置标准类  

               PHP中有很多 定义好的类,其中有一个叫  内置标准类。该类的内部什么都没有定义,可以理解为:

        class stdclass{    }

stdclass

        作用:1 可以临时存储数据:$obj2 -> p1 = 100;

                   2 当其他数据类型转换为对象类型的时候,得到就就是一个内置标准类(stdclass)的一个对象实例;

                    形式: $obj = (object)其他数据类型;

                    ①数组转为对象:数组的键名作为属性名,键值作为对应的值;数字下标的数组,不推荐转换,因为无法通过对象语法获取。

数组转对象 得到的是内置标准类的一个实例

                        ②null 转为对象 为空对象

内置标准类

                        ③其他 标量数据 (布尔(boolean),整型(interger),浮点型(float/double),   字符串(string)转为对象,键名为 固定的“scalar”,值为 该变量的值;

其他 标量数据 转为对象

        类型约束

            就是要求某个变量只能使用(接收,存储)某种指定的数据类型;

            PHP只支持在函数(或方法)的形参上,设定类型的约束目标,形式:

            function 函数名 (【要求使用的类型】形参1,【要求使用的类型】形参2.......){   }

            说明:1 定义一个函数的时候,可以设定约束类型也可以不设定;

                       2 如果设定了约束类型,该实参就必须是该类型,否则就会报错;

                       3 能够使用约束类型的就只有一下几种:数组(array),对象(使用类的名称,表示该实参必须是该类的一个实例),接口(使用接口的名称,表示该实参必须是该接口的类的一个实例)

    类型约束

        类相关的魔术方法

                序列化与反序列化技术

                序列化:就是将一个变量所代表的“内存”数据,转换为“字符串”形式并持久保存在硬盘上的一种做法。

                $v1  = 100;

                $s1 = serialize($v1); //将任何类型的变量数据,转化为字符串

                file_put_contents('要保存的目标文件名',$s1);//保存到文件中去

                反序列化:就是将序列化之后保存在硬盘上的“字符串数据”,恢复为其原来的内存形式的变量数据的一种做法。

                $s1 = file_get_contents( ‘保存序列化数据的目标文本文件’); //从一个文件里读出其中的所有字符

                $v1 =  unserialize( $s1 ); //将该字符串数据,反序列化转换为变量(数据)

序列化与反序列化

                对象的序列化和反序列化

                对象序列化只能保存其属性,而方法被忽略;而且会自动调用该对象所属类的魔术方法:__sleep()(前提是有该方法),且该方法必须返回一个数组,数组中是“计划”要进行序列化的属性名;

对象的序列化

                对象反序列化其实是恢复其原来保存起来的属性数据,而且,此时必然需要依赖该对象原本的所属类;对象在反序列化的时候,会自动调用该对象所属类的这个魔术方法:__wakeup()(前提是有该方法)。


             __tostring()魔术方法(常用)

              将一个对象“当做”一个字符串来使用的时候,会自动调用该方法,并且在该方法中,可以返回一定的字符串,以表明该对象转换为字符串之后的结果。

                注意:如果没有定义该方法,则对象无法当做字符串来使用。

__tostring 

         与类相关的方法属性

                魔术常量:以前的笔记中有的 __FILE__   __DIR__  __LINE__

                __CLASS__: 代表当前其所在的类的类名;

                __METHOD__:代表其当前所在的方法名;

魔术常量

        与类有关的系统函数:

        class_exists(“类名”), 判断一个类是否存在(是否定义过)

        interface_exists(“接口名”), 判断一个接口是否存在(是否定义过)

        get_class( $obj ), 获得某个对象$obj的所属类

        get_parent_class($obj ), 获得某个对象$obj的所属类的父类

        get_class_methods(), 获得一个类的所有方法名,结果是一个数组,里面存储的是这些方法的名称

        get_class_vars(), 获得一个类的所有属性名。结果是一个数组,里面存储的是这些属性的名称get_declared_classes() 获得“整个系统”所定义的所有类名;

        与对象有关的系统函数:

        is_object( $obj ): 判断某个变量是否是一个对象;

        get_object_vars( $obj ):获得一个对象的所有属性;结果是一个数组,里面存储的是这些属性的名称

        与类有关的运算符:

        instanceof:  判断一个“变量”(对象,数据),是否是某个类的“实例”;

   instanceof

        static关键字的新用法和总结(重要)

            static这个关键字,也可以像“self”一样,代表“当前类”,用于访问一个类的“静态属性或静态方法”;但,static,在应用中,更灵活,因此更常见。因为static,它代表的是“调用”当前方法的类,而不是“其代码所在的类”;self它就比较死板,只代表这个单词本身所在位置的所在类。

 static和self
上一篇下一篇

猜你喜欢

热点阅读