kingforce 发表于 2018-12-22 11:38:14

php学习_第8章_PHP面向对象的程序设计

  --对象的3大特性:封装,继承,多态。
  --对象概述
  从概念上讲什么是对象?对象就是一个东西,一个实体。
  php语言(大多面向对象程序语言)如何描述对象?借助成员属性、成员方法描述。
  成员属性描述对象的外观和状态;
  成员方法描述对象的功能。
  --类与对象的关系
  声明类-->实例化对象(创建对象)-->使用对象
  --类的声明

  [修饰类的关键字]>  {
   变量名 //成员属性的前面必须加修饰词,如果不确定用什么修饰词,就用var
  function 函数名
  { 函数体 }                                                   //成员方法
  }
  --保存类的文件
  通常一个文件只保存一个类,文件名中包含类名,比如:类名.class.php(这样见到文件名就知道保存的是类,也知道是什么类;另一方面,这样命名php才能够实现自动加载)
  --关于成员属性


[*]成员属性的前面必须加修饰词,如果不确定用什么修饰词,就用var.
[*]成员属性如果在不同实例化中可能取不同的值,不要给初始值。
  --对象的创建


[*]格式:$对象名 = new 类名;
[*]每创建一个对象,就在内存中分配一份空间。
  --对象的存储
  php语言中,字符串、数组、对象都是存储在堆(另外几种存储空间是:数据段,代码段,栈)中的。
  对象自身存储在堆中,对象变量(存储对象的地址,可以理解为c++中的指向对象的指针)存储在栈中。
  --php中的this指针
  php的成员方法中如果使用成员属性或者其他成员方法,需要手工写上$this(c++里不用写,默认是本对象,参见http://stark.blog.运维网.com/189176/696281)
  --php构造方法


[*]含义:php对象创建以后,第一个自动调用的方法。用来初始化对象(注意:是先创建了对象,才调用的方法)
[*]php4中,构造方法名与类名相同。
[*]php5中,构造方法选择使用魔术方法__construct(),所有类的构造方法都用这个名。使用这个名字的好处:修改类名称时,构造方法不用改名。
[*]为了版本兼容,这两个方法可以都写在一个类中,php5优先使用__construct()。
  --php析构方法


[*]方法名:__destruct()
[*]含义:对象被释放前,最后一个自动调用的方法。用来关闭一些资源,做一些清理工作。
[*]对象的释放时机:php(java)使用垃圾回收器自动释放垃圾对象(函数返回时,函数中声明的对象就是垃圾对象了)。c++中手动释放不用的对象(用delete函数)。
[*]手工释放方式:php中也可以手工释放对象。$对象名=null;
  --魔术方法


[*]含义:系统提供的一些方法(方法名系统给的),这些方法是系统自动调用的,且有特定的调用时机(比如__construct()在对象创建时调用)。
[*]使用方法:在类中写上这个方法,就可以使用。
[*]特点:都以__(两个下划线)开头。
[*]特权:魔术方法比较特殊,不受权限的限制,可以访问private成员以及protect成员。
[*]例子:
[*]用在类中的魔术函数

[*]__construct()    //构造函数
[*]__desctuct()    //析构函数
[*]__set()   //用"对象->属性 = 值"直接设置私有成员属性时,自动调用的方法
[*]__get()   //用"对象->属性"直接读取私有成员属性时,自动调用的方法
[*]__isset() //直接用isset()查看对象的私有属性是否存在时,自动调用的方法
[*]__unset() //直接用unset()删除对象的私有属性时,自动调用的方法
[*]__clone()
[*]__call() //调用不存在的成员方法时,自动调用此方法,用于处理异常
[*]__sleep() //对象串行化时,自动调用的方法,用于决定串行化哪些成员属性
[*]__weakup() //对象反串行化时,自动调用的方法,用于决定对成员属性进行哪些改动。
[*]__toString() //用echo 输出对象时,自动调用,用于快速获取对象的字符串表现形式

[*]其他魔术函数

[*]__autoload()//用于自动包含类的定义文件,只要用到类名,就会自动调用这个函数

  --封装性(面向对象的3大特性之一)


[*]含义:把对象的成员(方法成员,属性成员)结合成独立的单位,并尽可能隐藏对象的内部细节。
[*]关键字:public private protect
[*]封装的作用:

[*]对于方法:隐藏类实现的内部细节,类里面可能定义了100个方法,只有5个方法是需要对外的,另外95个都是为这5个服务的,所以把这95个隐藏起来是比较好的。仅开放必要的接口,也有利于别人了解该类。
[*]对于属性:避免了被外部修改为非法数据的危险。对于需要外部修改的属性,可以通过public方法来设置(经过方法改值或取值是可控的)。

  __get($proName)


[*]含义:用"对象->属性"直接读取私有(公有也用不着调用这个函数了)成员属性时,自动调用的方法
[*]参数:__get($proName)方法里有1个参数,就是需要返回属性的属性名(参数值是系统自动传入的)。
  __set($proName,$proValue)


[*]含义:用"对象->属性 = 值",直接设置私有(公有也用不着调用这个函数了)成员属性时,自动调用的方法
[*]参数:__set($proName,$proValue)方法里有2个参数,就是需要设置属性的属性名、属性值(参数值是系统自动传入的)。
  __isset($proName)


[*]含义:直接用isset()查看对象的私有属性是否存在时,自动调用的方法。
[*]参数:__isset($proName)里面有1个参数,传递需要查询的属性名。返回值应该为bool型。
  __unset($proName)


[*]含义:直接用unset()删除对象的私有属性时,自动调用的方法。
[*]参数:__unset($proName)里面有1个参数,传递需要删除的属性名。
  --继承性(面向对象的3大特性之一)


[*]作用:提高代码的可重用性(子类不用再写一遍父类的属性),可维护性(如果需要修改公共属性,修改父类就可以影响到所有子类)
[*]和C++的区别:C++是多继承的面向对象语言(同一个类可以有多个父类);PHP、Java是单继承(一个类只能有一个父类)
[*]声明方法:使用关键字extends去继承(扩展)一个父类。例如  


[*]class student extends person
[*]{}
  

子类可以继承父类的所有成员(对于private成员,子类是不能访问的)。

注意:子类中重载的方法,不能低于父类中的访问权限。(子类可以放大权限,不能缩小权限)
  --类的权限

private
protected
public
自己类中
Y
Y
Y
子类中
N
Y
Y
类外部
N
N
Y  --成员方法重载


[*]c++的重载:父类与子类的函数名相同,参数个数或参数类型不同。
[*]php的重载:只要子类和父类的方法名相同,子类的方法就覆盖父类的方法,实现重载。因为php函数的参数个数是可以任意加的,并且是弱类型的,所以按c++的重载方式显然不行。
[*]重载如果用于对父类方法的扩展,需要在子类方法中调用父类中被覆盖掉方法。
[*]对于子类的构造方法,如果父类中也有构造方法,一定要在子类中调用父类的构造方法。
  --子类方法中调用父类中被覆盖掉的方法
  在子类中写:父类名::方法名,或者是parent::方法名
  --php中常用的关键字:final,static,const
  --final关键字


[*]使用方法:用来修饰类、成员方法。不能修饰成员属性。
[*]作用:

[*]使用final修饰的类不能被子类继承。
[*]使用final修饰的方法,不能被子类方法覆盖(重载)。

  --static关键字


[*]static可以修饰成员属性、成员方法。不能修饰类。
[*]作用:

[*]用static修饰的成员属性,可以被类中的所有对象共享。
[*]用static修饰的成员方法,可以不用创建对象就使用方法。

[*]存储位置:静态成员属性存储在数据段中的。
[*]何时被加载:在类第一次被加载时,静态成员属性被分配到内存数据段中,以后再用到类,就从数据段中读取.
[*]什么是类被加载:只要在程序中使用这个类(类名出现就可以,不一定要创建对象)
[*]注意:静态成员(属性与方法)都要使用类名去访问,不用创建对象,不用对象去访问。
[*]使用方法(静态成员属性与静态成员方法):

[*]如果在类中使用静态成员,可以使用类名::静态成员。
[*]如果在类中使用静态成员,可以使用self代表本类,self::成员名

  --静态成员方法的注意事项:


[*]禁忌:静态方法中,不能访问非静态成员(包括非静态的属性与方法)。因为非静态成员需要对象来访问,而静态方法与对象无关,所以它也就不能访问非静态成员。
[*]什么时候用:如果一个方法能确保不访问非静态成员,可以把这个方法声明为静态方法(好处是不用创建对象,就能使用这个方法)。
[*]应用举例:单态设计模式中,用静态方法创建对象。
  --const关键字


[*]用途:修饰类的成员属性为常量。
[*]命名方式及取值范围:与define一样(名字全大写,在声明和使用时都不需要$符号。;取值为标量)
[*]访问方式:和static成员属性是一样(在类外部,使用 类名::常量名;在类内部,使用 self::常量名)。
[*]存储位置:和static成员属性一样,在数据段中。
[*]注意:

[*]只能用于修饰成员属性,不能用在类外(类外定义常量用define)。
[*]要在声明时就给初值。

[*]举例:
  


[*]class demo
[*]{
[*]    const HOST = "localhost";
[*]}
  

  --__call($methodName,$args)魔术方法


[*]作用:调用不存在的方法时,系统会报错,然后程序推出。__call($methodName,$args)魔术方法用于解决此情况。
[*]什么时候调用:会在调用一个不存在的成员方法时调用。
[*]参数:$methodName 不存在方法的方法名;$args不存在方法的参数组成的数组。
  __toString()魔术方法


[*]作用:用echo 输出对象时,自动调用,用于快速获取对象的字符串表现形式。
[*]什么时候调用:用echo直接输出对象时,自动调用。
[*]参数:无。
[*]返回值:字符串,要构建能够表现对象内容的字符串。
  --clone关键字


[*]为什么会有这个关键字:如果直接对象间赋值,比如$p1 = $p2的话,只是把$p2的指针赋值给了$p1,这两个引用还是指向了同一个对象。所以诞生了clone关键字,它指示系统创建一个新对象,并浅拷贝原来对象的属性。
[*]作用:创建一个对象,并浅拷贝原来对象的值(当一个对象被克隆时,PHP5将执行一个所有对象的属性的浅拷贝。任何对其它对象引用的属性将只保留引用。)。如果想实现深度拷贝,需要用到__clone()方法。
[*]使用方法:$p1 = clone $p2;
  __clone()魔术方法
  作用:使用clone关键字时自动调用此函数。可用于克隆对象时做特殊的操作(比如clone电视机对象,但又不想复制电视机编号,就用__clone()方法做特殊处理)。
  详细说明见:http://stark.blog.运维网.com/189176/699583
  __autoload()


[*]位置:魔术方法中唯一一个不在类中添加的方法,其他魔术方法都是作为类的成员方法。
[*]作用:当工程中类的定义文件比较多,包含起来很麻烦时,可以使用此方法,用于自动包含类的定义文件。
[*]什么时候调用:只要用到类名,就会自动调用这个函数。
[*]什么叫做用到类名:

[*]new一个对象,比如$p1 = new point;
[*]用类名引用方法,point::staMethod;

[*]典型案例:
  


[*]function __autoload($className)
[*]{
[*]    /**
[*]    *include前面一般都有判断,比如判断className字符串的后面6个字符是什么就到相应的目录去找文件
[*]    */
[*]    include "./".$className."class.php"; //为了能使用这个函数,类的定义文件一般都定义为 类名.class.php
[*]}
  

  由于linux系统区分文件名大小写,所以用strtolower($className) 将类名都转为小写。include "./".strtolower($className)."class.php";
  --对象串行化(序列化):将一个对象转换为二进制串。(对象是存储在内存中的,把它转换为二进制串就可以保存起来)


[*]作用:

[*]可以将对象长时间存储在数据库或文件中。
[*]对象在多个php文件中传输时,也需要用到。

[*]使用的函数:

[*]serialize()参数是一个对象,返回的是一个串行化的二进制串。//然后可以将二进制串存到文件中
[*]unserialize()参数是一个二进制串,返回的是一个新生成的对象。//需要提前从文件中读取二进制串。

  __sleep() 魔术方法


[*]什么时候调用:对象串行化时,自动调用的方法,用于决定串行化哪些成员属性。
[*]作用:将一个对象部分串行化。
[*]使用方法:只要这个方法中返回一个数组,数组中有几个元素(元素值就是成员属性名)就串行化几个成员属性。如果不加这个方法,则串行化所有成员属性。
  __wakeup
  作用:对象反串行化时,自动调用的方法,用于决定对成员属性进行哪些改动。
  --会创建新对象的情况


[*]new //会调用__construct()
[*]使用clone关键字赋值 //会调用__clone()
[*]unserialize() //会调用weakup()
  --抽象方法


[*]定义:如果一个类中的方法没有方法体(就是一个方法没有使用{},而直接使用分号结束),并且使用abstract关键字去修饰,就是抽象方法。
[*]例如:abstract function test(); //没有方法体,抽象方法
  function test() {} //有方法体,只是方法体为空
  --抽象类


[*]定义:如果一个类中有一个方法是抽象的,并且它本身不能实例化对象,它的子类可以创建,但子类必须重载父类的抽象方法,那么这个类就是抽象类。
[*]举例:抽象类必须使用abstract去修饰。abstract>
[*]注意:

[*]抽象类虽然是一种特殊的类,但它里面的其他成员与普通类一样(比如可以声明非抽象方法,成员属性)。
[*]抽象类不能实例化(不能通过抽象类去创建一个对象)。

[*]使用方法:
  要想使用抽象类,必须要一个类去继承抽象类,而且要想使用这个子类(用子类创建对象),子类就不能再是抽象类,子类必须重写父类的抽象方法(给抽象方法加上方法体)。


[*]作用:就是定义一些规范(抽象方法),让子类按照规范去实现自己的功能。
[*]设计抽象类的目的:就是要将你自己写的程序,加入到别人已写好的程序中去。(别人不必等你开发完小模块后再开发后面部分,他只需告诉你他都需要哪些方法)
  --接口技术


[*]定义:接口是一种特殊的抽象类。
[*]作用:接口的作用和抽象类相同,都是为了提供规范。
[*]设计接口的目的:为了多继承(虽然php里不这么说,但实际作用就是多继承)。php是单继承语言,那么用抽象类就只能在子类实现父类的抽象方法,如果想要同时实现多个类的抽象方法,就引出了接口。
[*]接口和抽象类的异:

[*]声明方式不同:声明接口用 interface 接口名{}
[*]成员方法不同:接口的所有方法必须都是抽象方法。(抽象类可以有普通方法)因为都是抽象方法,接口方法不用abstract修饰。
[*]成员属性不同:接口的所有属性必须都是常量。(抽象类可以有变量成员属性)
[*]接口中成员访问权限,必须都是public.(抽象类可以有protect成员)
[*]使用类去实现接口,不是extends,而是implements。
[*]实现接口时,不能再添加成员。(继承抽象类时,可以添加成员)
[*]一个类可以去实现多个接口。(一个类只能继承一个抽象类)

[*]接口和抽象类的同:都是为了提供规范,都自身不能实例化,需要子类去继承(对接口来说是实现)后再实例化。
[*]接口的使用方法:

[*]可以使用抽象类去实现接口的部分方法(当然抽象类还需要普通类去继承):

  


[*]abstract demo implements test
[*]{
[*]    fun1(){} //test接口还有fun2,在抽象类demo中没有实现
[*]}
  
还可以使用普通类去实现接口的全部方法:
  


[*]class demo implements test
[*]{
[*]    fun1(){}
[*]    fun2(){}
[*]}
  

  可以使用接口去继承接口:
  


[*]interface domo extends test
[*]{
[*]    fun3(){} //继承的接口,可以添加成员
[*]    fun4(){} //继承的接口,可以添加成员
[*]}
  

  可以同时实现多个接口,用逗号分隔多个接口名称:
  


[*]interface Demo
[*]{
[*]      const HOST="localhost";
[*]      const USER="Admin";
[*]
[*]      function fun1();
[*]      function fun2();
[*]}
[*]
[*]interface Demo2 extends Demo
[*]{
[*]    function fun3();
[*]
[*]    function fun4();
[*]}
[*]
[*]interface Demo3
[*]{
[*]    function fun5();
[*]    function fun6();
[*]}
[*]interface Demo4
[*]{
[*]    function fun7();
[*]}
[*]
[*]
[*]   class Testimplements Demo2,Demo3,Demo4
[*]{
[*]    function fun1(){
[*]
[*]    }
[*]
[*]    function fun2(){
[*]
[*]    }
[*]    function fun3(){
[*]
[*]    }
[*]
[*]    function fun4(){
[*]
[*]    }
[*]    function fun5(){
[*]
[*]    }
[*]
[*]    function fun6(){
[*]
[*]    }
[*]    function fun7(){
[*]
[*]    }
[*]}//同时实现了:Demo,Demo2,Demo3,Demo4几个接口
  

  可以在继承一个类的同时,实现一个或多个接口:(先继承,再实现)
  


[*]interface Demo {
[*]      const HOST="localhost";
[*]      const USER="Admin";
[*]
[*]      function fun1();
[*]      function fun2();
[*]}
[*]
[*]interface Demo2 extends Demo {
[*]    function fun3();
[*]
[*]    function fun4();
[*]}
[*]
[*]interface Demo3 {
[*]    function fun5();
[*]    function fun6();
[*]}
[*]interface Demo4{
[*]    function fun7();
[*]}
[*]
[*]class Hello {
[*]    function fun8(){
[*]
[*]    }
[*]}
[*]
[*]   class Test extends Hello implements Demo2,Demo3,Demo4 {
[*]    function fun1(){
[*]
[*]    }
[*]
[*]    function fun2(){
[*]
[*]    }
[*]    function fun3(){
[*]
[*]    }
[*]
[*]    function fun4(){
[*]
[*]    }
[*]    function fun5(){
[*]
[*]    }
[*]
[*]    function fun6(){
[*]
[*]    }
[*]    function fun7(){
[*]
[*]    }
[*]}
  

  --多态性(面向对象的3大特性之一)
  含义:“多态”是面向对象设计的重要特性,它展现了动态绑定(dynamic binding)的功能,也称为“同名异式”(Polymorphism)。
  多态的功能可让软件在开发和维护时,达到充分的延伸性(extension)。事实上,多态最直接的定义就是让具有继承关系的不同类对象,可以对相同名称的成员函数调用,产生不同的反应效果。
  --php代码和前台html混合
  目前所学的都是两种代码混合,使用mvc模式和模板技术后可以将两种代码分离,将逻辑层和表现层分离出来。
  --调用本类
  方法中可以使用常量"__CLASS__",表示本类的类名。
  --关于使用某个类的方法作为回调函数
  参数需要使用数组,数组有2个成员:array(类名,回调函数名),    例如:
  


[*]session_set_save_handler(array("类名","方法名"));//函数session_set_save_handler()
[*]                                        使用某类的方法作为回调函数。
  



页: [1]
查看完整版本: php学习_第8章_PHP面向对象的程序设计