第一章面向对象概述
一、结构化编程与面向对象编程的区别
在程序设计的早期,程序用流程图和自顶向下的方法设计。采用这种设计方法,程序员会将一个大的问题分解成更小的任务,然后为每个更小的任务编写一个过程(或函数)。最后,程序员会编写一个主过程来启动程序流程,随后根据程序流程走向,调用想要的其它过程。这种类型的程序设计被称为结构化编程。
20世纪70年代以后,面向对象编程(Object Oriented Programming,简称OOP)开始流行。OOP采用了一种完全不同的方法来开发计算机应用程序。在这种方法中,程序不是围绕着要解决的任务来设计,而是围绕着要解决的问题中的对象来设计。建立对象模型,将问题域化为不同的对象去处理。
1.二者的区别
在结构化编程中,程序围绕着要解决的任务来设计。
面向对象编程中,程序围绕着问题域中的对象来设计。
以下我们通过一个例子来说明:
主要是研究的方式不同
例子1,煮饭
结构化编程:
判断是否有米,水,电-->将洗过的米倒入锅里--->连接电源-->选择煮饭
结构化编程:使用流程控制图,过程化方式,一个步骤一个步骤执行。
面向对象:
原材料米,参与者水电源,工具电饭煲
面向对象:研究参与的对象,所有的操作都由人来控制完成。
过程中,电饭锅是加工的工具,米是原材料,而水和电源是参与者且必不可少。
假如某个公司想让我们编写一个发工资的程序。该公司的员工是每周发一次工资,但是员工薪酬体制有所不同:有些员工的工资按照日薪制,根据每周工作时间来计算报酬;某些员工的工资是固定的年薪。此外,还要计算工资中要扣除的社保、医保以及所得税。
例子2,工资发放
结构化的解决方案:
临时工,日薪*工作天数-税费
正式工,月薪-税费-医保-社保
面向对象的解决方案:
找对象:
描述对象的属性和行为
员工(类别)
工资(类别)[行为:税,(医保,社保)]
二、类和对象
1.什么是类?
类-->类别class
2.什么是对象?
对象-->object物质,物体的本源。客观存在的事物,万事万物皆对象
使用面向对象识别事物的方式:
类比-->归类
3.类和对象的关系?
人也是动物和其他动物的区别:人能够创造和使用工具
类是对象的抽象,对象是类的实例
类是具有相同属性和行为的一组对象的集合
在软件系统中,我们用类来模拟现实生活中的实体
4.类和对象
类(Class)是用来描述一个对象(Object):
类描述了每个对象应包括的数据
类描述了每个对象的行为特征
类是对一类事物描述,是抽象的、概念上的定义;
(类好像是在图纸上设计的楼房,楼房设计出来了,但这个楼房并不存在。)
对象是实际存在的该类事物的每个个体,因而也称实例(instance)。
(对象是实实在在存在的,照着楼房的设计图纸,高楼盖起来,可以住进去了。在计算机中,可以理解为,在内存中创建了实实在在存在的一个内存区域存储着这个对象。)
创建对象的过程称为 创建对象 也称为实例化。
三、掌握如何编写PHP类
1、创建类
PHP 中使用关键字 class 来定义一个类。类的命名一般使用首字符大写,而后每个单词首字符大写连接的方式方便阅读。
class Person
{
public $id; //序号
public $name; //姓名
public $birth; //生日
public $sex; //性别
}
类中的一个成员变量由如下部分组成:
访问修饰符。可以是public、private或protected
成员变量名称。成员变量名称必须是一个有效的标识符,后面用分号结束。
要注意格式
class RenLei {//RenLei叫标识符标识符默认首字母大写,用户自定义 //属性,//对对象进行描述,都是名称词 public $name; public $gender; //行为,主动性的动作,有什么功能 //弱类型语言,弱(弱化),灵活性高; function useTools(){ } }
每个类的定义都以关键字 class 开头,后面跟着类名,后面跟着一对花括号,里面包含有类的属性与方法的定义。
类名可以是任何非 PHP 保留字的合法标签。一个合法类名以字母或下划线开头,后面跟着若干字母,数字或下划线。以正则表达式表示为:
[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*。
一个类可以包含有属于自己的常量,变量(称为“属性”)以及函数(称为“方法”)。
当一个方法在类定义内部被调用时,有一个可用的伪变量 $this 。 $this 是一个到主叫对象的引用(通常是该方法所从属的对象,但如果是从第二个对象静态调用时也可能是另一个对象)。
2.书写属性和方法
class Person { //这里是属性 public $id; //序号 public $name; //姓名 public $birth; //生日 public $sex; //性别 //这里是行为 public function setName($name){ $this->name=$name; } public function getName(){ $this->name; } }
四、如何实例化对象
1、创建对象
$p = new Person();
使用 new 这个关键字创建对象
注意:
$p = new Person();也可以写成 $p = new Person;
但不建议使用后面的这种方式。
请各位同学写代码输出创建的对象,注意输出的内容格式。
new
要创建一个类的实例,必须使用 new 关键字。当创建新对象时该对象总是被赋值,除非该对象定义了构造函数并且在出错时抛出了一个异常。类应在被实例化之前定义(某些情况下则必须这样)。
如果在 new 之后跟着的是一个包含有类名的字符串,则该类的一个实例被创建。如果该类属于一个名字空间,则必须使用其完整名称。
在类定义内部,可以用 new self 和 new parent 创建新对象。
当把一个对象已经创建的实例赋给一个新变量时,新变量会访问同一个实例,就和用该对象赋值一样。此行为和给函数传递入实例时一样。可以用克隆给一个已创建的对象建立一个新实例。
五、如何访问对象的属性和方法
$实例化对象变量名->方法/属性
“->”指向
在类的成员方法里面,可以用 ->(对象运算符): $this->property (其中 property 是该属性名)这种方式来访问非静态属性。静态属性则是用 ::(双冒号): self::$property 来访问。更多静态属性与非静态属性的区别参见 Static 关键字。
当一个方法在类定义内部被调用时,有一个可用的伪变量 $this 。 $this 是一个到主叫对象的引用(通常是该方法所从属的对象,但如果是从第二个对象静态调用时也可能是另一个对象)。
::class
自 PHP 5.5 起,关键词 class 也可用于类名的解析。使用 ClassName::class 你可以获取一个字符串,包含了类 ClassName 的完全限定名称。这对使用了 命名空间 的类尤其有用。
六、属性
类的变量成员叫做“属性”,或者叫“字段”、“特征”,在本文档统一称为“属性”。属性声明是由关键字 public,protected 或者 private 开头,然后跟一个普通的变量声明来组成。属性中的变量可以初始化,但是初始化的值必须是常数,这里的常数是指 PHP 脚本在编译阶段时就可以得到其值,而不依赖于运行时的信息才能求值。
有关 public,protected 和 private 的更多详细信息。
Note:
为了向后兼容 PHP 4,PHP 5 声明属性依然可以直接使用关键字 var 来替代(或者附加于)public,protected 或 private。但是已不再需要 var 了。在 PHP 5.0 到 5.1.3,var 会被认为是废弃的,而且抛出 E_STRICT 警告,但是 5.1.3 之后就不再认为是废弃,也不会抛出警告。
如果直接使用 var 声明属性,而没有用 public,protected 或 private 之一,PHP 5 会将其视为 public。
在类的成员方法里面,可以用 ->(对象运算符): $this->property (其中 property 是该属性名)这种方式来访问非静态属性。静态属性则是用 ::(双冒号): self::$property 来访问。更多静态属性与非静态属性的区别参见 Static 关键字。
当一个方法在类定义内部被调用时,有一个可用的伪变量 $this 。 $this 是一个到主叫对象的引用(通常是该方法所从属的对象,但如果是从第二个对象静态调用时也可能是另一个对象)。
七、类变量
可以把在类中始终保持不变的值定义为常量。在定义和使用常量的时候不需要使用 $ 符号。
常量的值必须是一个定值,不能是变量,类属性,数学运算的结果或函数调用。
接口(interface)中也可以定义常量。更多示例见文档中的接口部分。
自 PHP 5.3.0 起,可以用一个变量来动态调用类。但该变量的值不能为关键字(如 self,parent 或 static)。
八、自动加载类
很多开发者写面向对象的应用程序时对每个类的定义建立一个 PHP 源文件。一个很大的烦恼是不得不在每个脚本开头写一个长长的包含文件列表(每个类一个文件)。
在 PHP 5 中,不再需要这样了。可以定义一个 __autoload() 函数,它会在试图使用尚未被定义的类时自动调用。通过调用此函数,脚本引擎在 PHP 出错失败前有了最后一个机会加载所需的类。
补充:spl_autoload_register() 提供了一种更加灵活的方式来实现类的自动加载。因此,不再建议使用 __autoload() 函数,在以后的版本中它可能被弃用。
Note:
在 5.3.0 版之前,__autoload 函数抛出的异常不能被 catch 语句块捕获并会导致一个致命错误。从 5.3.0+ 之后,__autoload 函数抛出的异常可以被 catch 语句块捕获,但需要遵循一个条件。如果抛出的是一个自定义异常,那么必须存在相应的自定义异常类。__autoload 函数可以递归的自动加载自定义异常类。
Note:
自动加载不可用于 PHP 的 CLI 交互模式。
Note:
如果类名比如被用于 call_user_func() ,则它可能包含一些危险的字符,比如 ../。 建议您在这样的函数中不要使用用户的输入,起码需要在 __autoload() 时验证下输入。
九、构造函数
构造方法又称为构造函数,是对象被创建时自动调用的方法,用来完成类初始化的工作。
构造函数和其它函数一样,可以传递参数,可以设定参数默认值。
构造函数可以调用属性,可以调用方法。
构造函数可以被其它方法显式调用。
构造函数可以被继承
//构造函数
public function __constract($name, $birth, $sex){
$this->name=$name;
$this->birth=$birth;
$this->sex=$sex;
}
注意:是两个 _
__两根下划线开头又称为魔术方法
void __construct ([ mixed $args [, $... ]] )
PHP 5 允行开发者在一个类中定义一个方法作为构造函数。具有构造函数的类会在每次创建新对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作。
Note: 如果子类中定义了构造函数则不会隐式调用其父类的构造函数。要执行父类的构造函数,需要在子类的构造函数中调用 parent::__construct() 。如果子类没有定义构造函数则会如同一个普通的类方法一样从父类继承(假如没有被定义为 private 的话)。
为了实现向后兼容性,如果 PHP 5 在类中找不到 __construct() 函数并且也没有从父类继承一个的话,它就会尝试寻找旧式的构造函数,也就是和类同名的函数。因此唯一会产生兼容性问题的情况是:类中已有一个名为 __construct() 的方法却被用于其它用途时。
与其它方法不同,当 __construct() 被与父类 __construct() 具有不同参数的方法覆盖时,PHP 不会产生一个 E_STRICT 错误信息。
自 PHP 5.3.3 起,在命名空间中,与类名同名的方法不再作为构造函数。这一改变不影响不在命名空间中的类。
<?php /** * Created by PhpStorm. * User: Dell-pc当前操作系统的用户名 * Date: 2017/7/13 * Time: 14:31 */ class test { /*性别*/ public $name; /*性别*/ public $gender; /* * 构造函数方法 __construct 它是一个魔术方法 * 它是在创建对象时被自动调用 * 一个类中有且只有一个构造函数 * * 构造函数可以带参数,这些参数通常是用来给类的 属性进行初始化赋值 * */ // public function __construct() // { // echo "我是一个构造函数"; // } public function __construct($name,$gender) { //$name,$gender和外面的$name$gender不一样 //$this它指代的是当前类的对象要加上$ $this->name=$name; $this->gender=$gender; echo "我是一个构造函数"; } /* * 测试使用的方法 * @param参数值说明 * @return返回值的说明 * */ public function testOutput() { echo "ided"; } } //实例化对象 $test=new test("lisi","dd"); //$test=new 类名 //调用属性和方法 $test->gender=‘李四‘;//调用属性并赋值 $test->testOutput(); ?>
十、析构函数
析构函数:当某个对象成为垃圾或者当对象被显式销毁时执行。自动被调用
//析构函数
public function __destruct(){}
__destruct() 析构函数,是在垃圾对象被回收时执行。
析构函数也可以被显式调用,但不要这样去做。
析构函数是由系统自动调用的,不要在程序中调用一个对象的虚构函数。
析构函数不能带有参数。
GC(Garbage Collector)
在 PHP 中,没有任何变量指向这个对象时,这个对象就成为垃圾。 PHP 会将其在内存中销毁。
这是 PHP 的 GC(Garbage Collector)垃圾处理机制,防止内存溢出。
当一个 PHP 线程结束时,当前占用的所有内存空间都会被销毁,当前程序中的所有对象同样被销毁。
void __destruct ( void )
PHP 5 引入了析构函数的概念,这类似于其它面向对象的语言,如 C++。析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。
和构造函数一样,父类的析构函数不会被引擎暗中调用。要执行父类的析构函数,必须在子类的析构函数体中显式调用 parent::__destruct() 。此外也和构造函数一样,子类如果自己没有定义析构函数则会继承父类的。
析构函数即使在使用 exit() 终止脚本运行时也会被调用。在析构函数中调用 exit() 将会中止其余关闭操作的运行。
Note:
析构函数在脚本关闭时调用,此时所有的 HTTP 头信息已经发出。脚本关闭时的工作目录有可能和在 SAPI(如 apache)中时不同。
Note:
试图在析构函数(在脚本终止时被调用)中抛出一个异常会导致致命错误。
<?php /** * Created by PhpStorm. * User: Dell-pc当前操作系统的用户名 * Date: 2017/7/13 * Time: 14:31 */ class test { /*性别*/ public $name; /*性别*/ public $gender; /* * 构造函数方法 __construct 它是一个魔术方法 * 它是在创建对象时被自动调用 * 一个类中有且只有一个构造函数 * * 构造函数可以带参数,这些参数通常是用来给类的 属性进行初始化赋值 *可以传入默认值 * 可以调用属性方法 */ // public function __construct() // {echo $name.$gender; // echo "我是一个构造函数"; // } public function __construct($name,$gender) { //$name,$gender和外面的$name$gender不一样 //$this它指代的是当前类的对象要加上$ $this->name=$name; $this->gender=$gender; echo "我是一个构造函数<br/>"; } // 设置默认值 // public function __construct($name="ss",$gender="sss") // { // //$name,$gender和外面的$name$gender不一样 // //$this它指代的是当前类的对象要加上$ // $this->name=$name; // $this->gender=$gender; // echo "我是一个构造函数"; // } /* * 调用了析构函数__destruct魔术方法 * 它是在对象被销毁时自动被调用 *不能传入参数 * */ public function __destruct(){ echo "执行完毕了,出现析构函数<br/>"; } /* * 测试使用的方法 * @param参数值说明 * @return返回值的说明 * */ public function testOutput() { echo "ided<br/>"; } } //实例化对象 $test=new test("lisi","dd"); //$test=new 类名 //调用属性和方法 $test->gender=‘李四‘;//调用属性并赋值 $test->testOutput(); //清除析构函数变量 //$test=null; echo "完毕<br/>"; //析构函数出现在这后面 ?>
自动被调用,一般不手动调用,构造函数和析构函数都不建议被直接调用;析构函数不能带参数