面向对象编程
- 使用现有的技术来解决
- 使用面向对象的方式来解决
- 代码来一个快速入门的案例
- 说明
- class 是一个关键字,表示这是一个类,不能修改
- public $name , 是一个成员属性, 当我们类定义的{} 中定义的变量,就是一个成员属性
- public 是访问修饰符, 他是用于控制成员属性(变量)的访问范围的, 除了public还有两个,protected 和 private ,后面我们会详细介绍
- $cat1 = new Cat , 这个叫实例化一个对象, $cat1 就是一个对象, new 是一个关键字,表示新创建一个对象
- $cat1->name = '小白'; 表示给成员属性赋值,-> 符号叫做对象运算符
- 当我们需要看一个对象的情况时,我们可以通过 var_dump 来输出该对象
1.3 php支持面向对象
职业规划:
PHP + 前端技术 ===> 全栈工程师
架构师
python(对项目架构和运维[负载,读写分离,优化等等 ,大流量,大并发,大数据]) + linux(centos/ubuntu) + unix(freebsd, solars) + 算法
cto => 首先技术官
ceo => 首先执行官
- 介绍
在面向对象编程中,最重要的概念就是 类 和对象,因此我们必须将他们的关系和区别搞清楚.
举例说明:
说明: 从上面的代码我们可以看出
- 一个类可以创建多个对象
- 不同的对象的标识符#编码,是不一样的,有系统在创建对象时分配的标识符,按编号的顺序分配
class 类名{
访问修饰符 成员属性1;
访问修饰符 成员属性2;
//.....
}
- 文档说明
类的变量成员叫做“属性”,或者叫“字段”、“特征”,在本文档统一称为“属性”。属性声明是由关键字 public,protected 或者 private 开头,然后跟一个普通的变量声明来组成。属性中的变量可以初始化,但是初始化的值必须是常数,这里的常数是指 PHP 脚本在编译阶段时就可以得到其值,而不依赖于运行时的信息才能求值。
- 通俗说明:
成员属性是类的一个组成部分,一般是基本数据类型(整数,字符串等),
也可是复合类型(对象、数组) , 资源类型。比如我们前面定义猫类的
public $age 就是成员属性。
- 代码举例说明
说明
- 在使用默认构造方法时,创建对象的
$对象名 = new 类名()
$对象名 = new 类名
等价
举例:
- 如何访问成员属性
- 类名的规范说明
类名不区分大小写.
类名命名规范
关于函数,变量,常量,接口等等的命名规范,请参考手册.
1.9 对象传递方式(重点, 难点)
- 先请大家看一段代码,从而引起思考
注意当 对象传递方式是 $p1 = $p2 , 分析如上图
注意当 对象传递方式是 $p1 = &$p2 , 分析如上图
1.10成员方法(函数)
- 看一个需求
当我们需要让对象完成某个任务(比如计算,比如上传下载文件,分页等等), 就需要在类中定义函数, 这时我们就将这样的函数称为 成员方法.
- 举例说明:
代码走:
原理分析图如下:
- 成员方法的基本语法
class 类名{
成员属性;
访问修饰符 function 成员方法1名(形参){
方法体;
return 语句;//[是有程序员自己决定的,]
}
访问修饰符 function 成员方法1名(形参){
方法体;
return 语句;//
}
}
说明
- 成员方法定义在类中.
- 成员方法前面可以有访问修饰符,如果你不写,默认为public
- 成员方法的运行原理和普通的函数是一样的.
- 成员方法的小结
- 类定义的进一步完善
第 2 章 构造方法(函数)
什么是构造函数呢?在回答这个问题之前,我们来看一个需求:前面我们在创建人类的对象时,是先把一个对象创建好后,再给他的年龄和姓名属性赋值,如果现在我要求,在创建人类的对象时,就指定这个对象的年龄和姓名,该怎么做?
- 基本语法
class 类名{
//构造函数
访问修饰符 function __construct(形参列表){
//可以对成员属性进行初始化.
}
}
说明
- 构造函数的访问修饰符可以是 public , protected, private , 一般情况下是public ,默认就是public
- __construct 是关键字,不能修改, __ 是两个_ 下划线。
- 构造函数没有返回值, 即没有return
- 构造函数是系统调用的,程序员不能显示调用
走代码:(基本的使用案例)
- 构造函数没有返回值,即没有return, 就算写了也没有用处
- 在创建一个类的新对象时,系统会自动的调用该类的构造方法完成对新对象的初始化
- 构造函数的作用是完成对成员属性的初始化任务,而不是创建对象本身. 所以以后在oop编程中,需要对成员属性进行初始化,则将这段代码放在构造函数中即可
- 在一个类中,构造函数有且只能有一个, 如果定义多个,就会报错.
- 在php4中,可以使用 类名作为构造函数,在php5中也支持
- 如果在类中,没有定义构造函数,那么会有一个默认的构造函数,形式如下,举例说明
- 如何将一个对象的属性输出并显示
说明: 通过上面的案例,我们讲解了两个重要的点
- 如果显示成员属性的值
- 深刻理解了$this 的指向当前调用对象的特点.
- this的使用注意事项
this这个关键字,只能在类的方法中使用,而不能在类的外部使用.
基本的说明: 文档的说明:
PHP 5 引入了析构函数的概念,这类似于其它面向对象的语言,如 C++。析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行
我们来理解一下上面的话
- PHP5中引入的一个技术
- 某个对象的所有引用都被删除
- 使用unset(对象名), 将对象名销售
- $对象名 = null;
- $对象名 = 'abc'
- 显示销毁
上面写的三种方式,都是显示销毁, 所谓显示销毁就是程序员主动的删除对象引用.
如果程序员不去显示销毁对象,那么在程序执行完毕后,这个对象就会被系统销毁,这个就是系统销毁
3.2 php文件执行的流程
画图:
- 基本语法
class 类名{
public function __destruct(){
//函数体
//析构函数的最重要的作用,就是释放对象创建的资源
//比如 数据库连接, 文件句柄, 绘图句柄..
}
}
说明
- 析构函数都是public
- __destuct 是关键字,不要修改
- 析构函数没有形式参数
- 析构函数是系统调用
- 析构函数在如下情况会被系统调用
- php文件执行完毕
- 某个对象的所有引用都被删除后, 马上就会调用析构函数
- 快速入门案例
我们使用析构函数完成对资源的及时释放
说明
- 关于在析构函数中释放资源的问题,如果我们对效率没有很高很特殊的要求,完全可以不使用析构函数.
- 如果我们不确定代码后面是否还会使用资源(比如链接),那么我们建议最好不要使用析构函数
- 项目有特殊和明确的要求时,我们可以使用析构函数,显示的销毁对象是,在析构函数中,释放资源.
第 4 章 魔术方法
4.1 魔术方法一览
说明
- 魔术方法都是系统提供,程序员使用即可.
- 所有的魔术方法,前面都是以 __ 开头的 _是两个下划线.
- 我们在自定义函数时,就不要使用 __开头了.
- 魔术方法是在满足某个条件(一会一个一个的说明)时,有系统自动的调用.
4.2 访问控制修饰符的基本入门介绍
- 介绍
因为魔术方法和访问修饰符关系密切,因此我们需要先学习一下访问控制修饰符的基本知识, 这里我们先讲一个基本的介绍.
- 文档的介绍:
对属性或方法的访问控制,是通过在前面添加关键字 public(公有),protected(受保护)或 private(私有)来实现的。被定义为公有的类成员可以在任何地方被访问。被定义为受保护的类成员则可以被其自身以及其子类和父类访问。被定义为私有的类成员则只能被其定义所在的类访问
- 访问控制修饰符可以修饰成员属性,也可以修饰方法.
- 有三种 public , protected 和 private
- 使用代码来说明
4.3 魔术方法之-__get 和 __set函数
- 基本的介绍
- 当程序员去使用不可以访问的属性时,系统就会调用__get方法.
- 不可以访问的属性指的是(1 . 该属性不存在 2. 直接访问了protected或者private属性)
- 当程序员去给不可以访问的属性直接赋值,系统就会调用__set方法
- 举例说明
需求是: 如果对象有一个成员变量是private、protectd的,我希望在在类的外部通过 : $对象名->变量名的方式来赋值和取值,怎么办?
- 课堂练习
4.4 魔术方法之-__isset 和 __unset函数
- 基本介绍
- 当对不可访问的属性进行了 isset($对象名->属性), empty($对象名->属性)操作,那么__isset函数就会被系统调用。
- 不可访问的属性 仍然和前面说的一样 。
- 当对不可访问的属性进行了 unset($对象名->属性), 那么__unset函数就会被系统调用
- 代码说明
- 补充说明一下语法现象-属性重载
- 补充说明一下-property_exists()函数
<?php header('content-type:text/html;charset=utf-8'); //property_exists说明
class A{ public $name; protected $food;
public function __construct($name, $food){ $this->name = $name; $this->food = $food; } }
$a = new A('小猫', '鱼儿');
unset($a->name);
echo'<pre>'; var_dump($a);
if(property_exists($a, 'name')){ echo '<br> name属性存在'; }
//属性的重载 $a->age = 100;
echo '<pre>'; var_dump($a);
if(property_exists($a, 'age')){ echo '<br> age属性存在'; }else{ echo '<br> age属性不存在'; }
unset($a->age); echo '<pre>'; echo '<br>---------<br>'; var_dump($a);
if(property_exists($a, 'age')){ echo '<br> age属性存在'; }else{ echo '<br> age属性不存在'; }
//property_exists(对象名, 属性) //1. 先判断该对象是否有这个属性,如果有则返回真. //2. 如果该对象没有有这个属性, 则继续判断该对象对应的类是否定义过这个属性,如果定义过仍然返回真,否则才返回假
|
4.5 魔术方法之-__toString 函数
- 基本介绍:
当我们希望将一个对象当做字符串来输出时,就会触发__toString魔术方法.
- 代码说明
- 小练习
做两个怪物!
4.6 魔术方法之-__clone函数
- 基本介绍 :
当我们需要将一个对象完全的赋值一份, 保证两个对象的属性和属性值一样,但是他们的数据库空间独立,则可以使用对象克隆。
- 案例说明
说明
- 当我们 $对象1 = clone $对象2, 会触发 __clone 方法
- 如果我们希望在克隆时,修改某个属性,则在__clone方法中去修改即可
- 如果我们希望阻止克隆,只需要将 __clone 魔术方法申明为private 即可.
4.7 魔术方法之-__call函数
- 基本介绍:
- 当我们调了一个不可以访问的成员方法时,__call魔术方法就会被调用.
- 不可以访问的成员方法的是指(1. 该成员方法不存在, 2. 成员方法是protected或者 private)
- 需求
我们就是希望,在类的外部直接调用不可访问的成员方法(private , protected).
- 案例说明
- 课堂小练习
点评:
第 5 章 类的自动加载
5.1 看一个需求
说明
- 在我们的开发中, 一个类对应一个文件,其命名方式为 类名.class.php
- 在需要某个类时,通过 include 或者 require 引入即可.
- 问题请思考,如果一个文件使用到多个类,怎么办?
5.2 使用传统的方法来解决
5.3 对代码优化,使用类的自动加载来完成
5.4 对代码思考,对代码进行灵活性的处理
- 分析和思路
- 对应的代码
common.php 文件
5.5 使用spl_autoload_register 的高级方式(了解)来完成类的自动加载
- 一个案例
第 6 章 静态属性
6.1 看一个开发的需求
6.2 思路(使用现有的技术解决)
- 思路: 定义一个全局的变量 $total_num, 当有一个小朋友加入游戏时,我们就加1, 当我们需要查看有多少小朋友玩时,直接输出.
- 代码实现 :
6.3 对上面代码的进行分析和优化
- 分析: 虽然可以解决问题,但是不是以面向对象的方式来解决,因此我们需要优化
- 解决方式: 使用静态变量来完成:静态变量是属于所有对象, 因此可以被所有的对象共享.
- 代码解决:
- 内存的分析图
6.4 静态变量的其它说明
- 基本概念的再说明
静态属性是该类的所有对象共享的变量,任何一个该类的对象去访问它时,取到的都是相同的值,同样任何一个该类的对象去修改它时,修改的也是同一个变量。这个从前面的图也可看出来.
- 定义静态属性
- 访问修饰符 static 静态属性名;
- static 访问修饰符 静态属性名;
说明上面两种方式是等价的.
6.5 如何访问静态属性
- 在类的内部访问
可以使用两种方式 self::$静态属性名 , 类名::$静态属性名
:: 叫 范围解析符.
举例:
- 在类的外部访问
如果要在类的外部访问静态属性,静态属性需要是public ,否则也不能直接访问, 访问的形式是 类名::$属性名;
- $this和self的区别
6.6 静态属性的使用注意事项
6.7 课后练习题
<?php header('content-type:text/html;charset=utf-8'); /* 要求: 请设计一个Person类, (有 名字, 年龄 和 蛋糕 三个属性) 蛋糕一共1000块,是所有人共享的. 创建唐僧师徒四人,他们每人都吃蛋糕, 唐僧每天吃 3块,悟空吃5块,沙和尚吃9块,猪八戒吃 30块. (编写一个 eat方法来吃) 问两天后,还剩多少块蛋糕,(编写一个 showCake() 来显示) 请计算,蛋糕一共可以吃多少天.
*/
class Person{ public $name; public $age; // 蛋糕一共1000块,是所有人共享的, 因为共享的,因此我们应该设为static protected static $cakeNum = 1000;
//构造函数 public function __construct($name, $age){ $this->name = $name; $this->age = $age; }
//编写一个eat方法 public function eat($num){
//判断一下是否够吃 if(self::$cakeNum >= $num){ self::$cakeNum -= $num; return true; }else{
echo '<br> 当' .$this->name. ' 想吃 ' . $num . ' 块蛋糕, 不够了,不能吃了'; return false; } }
//编写一个方法,显示还有多少块蛋糕 public function showNum(){
echo '<br> 当前还有 ' . self::$cakeNum . ' 蛋糕...'; }
}
//使用 //问两天后,还剩多少块蛋糕,(编写一个 showCake() 来显示) //1. 创建四个对象 $monk = new Person('唐僧', 30); $monkey = new Person('悟空', 500); $pig = new Person('八戒', 400); $sMonk = new Person('沙僧', 300);
//2. 统计两天后 $day = 20; for($i = 0; $i < $day; $i++){
if(!$monk->eat(3)){ break; } if(!$monkey->eat(5)){ break; } if(!$sMonk->eat(9)){ break; } if(!$pig->eat(30)){ break; } }
echo '<br> 一共 可以吃 ' . ($i+1) . '天';
/* //思想 【程序员 思想=====(锻炼)=====>代码(php技术) 】 $count_day = 0; while(true){
if(!$monk->eat(3)){ break; } if(!$monkey->eat(5)){ break; } if(!$sMonk->eat(9)){ break; } if(!$pig->eat(30)){ break; }
$count_day++; }
*/
//3. 看看还剩多少块
$monk->showNum(); |
第 7 章 静态方法
7.1 基本的介绍
当程序员需要对静态属性进行操作时,可以定义静态方法来处理, 静态方法是专门用于操作静态属性.
- 静态方法的基本语法
class 类{
访问修饰符 static function 函数名(形参){
//函数体
}
}
说明
- 静态方法是在类中定义的
- static 是关键字,不能修改.
- 静态方法专门用于操作静态属性
- 静态方法可以通过类名直接调用. 形式时候 类名::静态方法名(参数 )
- 快速入门案例
7.2 静态方法的细节讨论
- 在类外部调用静态方法: 类名::静态方法名 或者 对象名->静态方法名 或者 对象名::静态方法(语法支持,但是不推荐)
举例说明:
- 在类内部调用静态方法: self::静态方法名 或者 类名::静态方法名 , 通过 $this也可以
举例说明:
- 注意:静态方法中只能访静态属性,不能访问非静态属性(普通属性, 没有static)
举例:
- 普通的成员方法,可以访问静态属性和非静态属性
- 如果我们的静态方法是protected 或是是 private 则也不能在类的外部使用
7.3 静态属性和静态方法的最佳实践-单例模式
- 先看实际的需求
- 代码实现
第一种版本-ok
- 第二种写法(推荐使用)
- 上面代码对应的示意图:
- 知识点的补充
第 8 章 OOP编程的三大特征-封装
8.1 基本介绍
oop编程的三大特征是: 封装性, 继承, 多态. 说明一下,在php面向对象编程中,多态提的并不是很多,因为php本身就是天生的多态.
8.2 抽象
在面向对象编程中,将一类事物的共有的属性(成员属性)和行为(成员方法)提取出来,形成一个模板(类), 这种解决问题的方法就是抽象.
8.3 抽象的实际案例
代码说明:
8.4 封装的基本概念
8.5 封装的具体实现-访问控制符
- 说明: 在php中,提供了三种访问控制符 public , protected 和private, 访问控制的访问是 public >protected > private. 具体我们看一个图:(重点)
总结:
public 类内部、外部和子类都可以访问;
protected 表示受保护的,只有本类或子类可以访问;
private 表示私有的,只有本类内部可以使用;
强调: 上面的说的访问控制访问,对属性和成员方法都起作用.
- 代码举例说明
8.6 如何访问protected和private属性的三种形式
- 使用魔术方法__get 和 __set 来实现对protected 和 private 属性的操作
总结
- 优点: 简单,一对__set 和 __get 就可以搞定所有的private , protected属性
- 缺点: 不够灵活,没有办法对各个属性进行控制和验证.
- 对每一个private 和 protected 属性提供一对get/set方法, 这样就可以分别控制,各个属性,并进行验证.
举例说明:
说明
- 优点: 可以对每个属性进行验证,因此很灵活.
- 缺点: 会造成有比较多的setXxx 和 getXxx方法,但是这个没有什么大的问题.
- 推荐使用这种方法,在实际开发中,这种方式比较多.
- 写一个成员方法,可以根据业务逻辑,一次性对多个属性进行批量操作 。
举例说明:
<?php header('content-type:text/html;charset=utf-8');
//Movie(名称,导演,成本(protected),票房[ticket_office](private)) //updateInfo() showAllInfo()
class Movie{ public $name; public $director; protected $cost; private $ticketOffice;
public function __construct($name, $director, $cost){ $this->name = $name; $this->director = $director; $this->cost = $cost; }
//显示一下电影信息 public function showAllInfo(){ echo '<br> 电影的信息如下:'; echo '<br> name = ' . $this->name; echo '<br> director = ' . $this->director; echo '<br> cost = ' . $this->cost; echo '<br> tickeoffice = ' . $this->ticketOffice; }
public function updateInfo($director, $cost, $ticketOffice){
//简单方式 // $this->director = $director; // $this->cost = $cost; // $this->ticketOffice = $ticketOffice;
//结合setXxx 来完成 $this->setDirector($director); $this->setCost($cost); $this->setTicketOffice($ticketOffice);
}
//setXxx GetXxx
public function SetDirector($director){ $this->director = $director; }
public function getDirector(){ return $this->director; }
public function setCost($cost){
//加入数据的验证和判断 if(is_numeric($cost) && $cost > 0.0){ $this->cost = $cost; }else{ echo '<br> 输入成本格式有问题 '; } }
public function getCost(){ return $this->cost; }
public function setTicketOffice($ticketOffice){
//加入数据的验证和判断 if(is_numeric($ticketOffice) && $ticketOffice > 0.0){ $this->ticketOffice = $ticketOffice; }else{ echo '<br> 输入票房格式有问题 '; } }
public function getTicketOffice(){ return $this->ticketOffice; }
}
$movie = new Movie('葫芦娃', '老爷子', 60000);
$movie->showAllInfo();
echo '<br>***********<br>'; $movie->updateInfo('老韩', 4000, 89000);
$movie->showAllInfo(); |
8.7 在开发中,如何选择操作方式
- 如果我们希望直接通过 $对象名->属性名的方式来操作属性,则使用__set 和 __get 函数即可
- 如果我们希望对各个属性分别进行验证,则使用setXxx 和 getXxx
- 如果希望同时操作多个属性,选择第三种
- 项目经理要求.
8.8 封装的细节说明
- 普通属性要定义为公有,受保护,私有之一。如果用 var 定义,则被视为公有。静态属性可以不指定访问修饰符,默认是public
举例说明:
- 类中的方法可以被定义为公有,私有或受保护。如果没有设置这些关键字,则该方法默认为公有(不管这个方法是静态的,还是非静态都满足这个规则)
8.9 对象运算符的连用现象
要求是 : 通过一个学生对象,可以访问到该学生所在班级的信息.
代码实现:
对应的原理分析图:
8.10课后练习题
//评讲....
<?php header('content-type:text/html;charset=utf-8'); /*
要求: 编写一个Dog类(名字,年龄,性别,主人) 编写一个Master类(名字,年龄,宠物狗) 创建一个Dog对象和Master对象,通过Dog对象可以找到对应主人的信息,通过Master对象可以找到对应宠物狗的信息[提示,需要各写一个方法.]
*/
class Dog{
public $name; private $age; private $sex; private $master; public function __construct($name, $age, $sex, $master){ $this->name = $name; $this->age = $age; $this->sex = $sex; $this->master = $master; }
public function setMaster($master){
$this->master = $master; }
public function getMaster(){
return $this->master; }
public function showMasterInfo(){
echo '<br> 主人的信息是'; echo '<br> 主人名字是 ' . $this->master->name; echo '<br> 主人年龄是 ' . $this->master->getAge(); }
}
class Master{
public $name; private $age; private $dog;
public function __construct($name, $age, $dog){ $this->name = $name; $this->age = $age; $this->dog = $dog; }
public function setDog($dog){ $this->dog = $dog; }
public function getDog($master){
return $this->master; }
public function setAge($age){ $this->age = $age; }
public function getAge(){
return $this->age; } }
//创建一只狗 $dog = new Dog('狼牙', 3, 'boy', null);
//创建一个人 $master = new Master('老吴', 32, $dog);
echo '<pre>'; var_dump($master);
$dog->setMaster($master); var_dump($dog);
//显示主人的信息 $dog->showMasterInfo(); |
第 9 章 OOP编程的三大特征-继承
9.1 看一个实际的需求(问题)
开发一个学生考试系统,学生可以考试并且测评分数,并显示考了多少分.(小学生,大学生.)
代码:
分析问题
- Pupil 类和 Graduate 类,相似度很高,很多相同的属性和方法.
- 这时已经出现了代码的冗余, 这样不利于类的管理和维护.
- 解决的方法就是继承.
9.2 继承的基本思想是
9.3 使用继承的方式对上面的代码进行改写
1
9.4 继承的概念在说明
说明
- 继承的根本作用就是解决代码的复用性,减少冗余度 , 同时利用类的维护和扩展
- 继承时的关键字是 extends , 这个是固定的,不能修改.
9.5 继承的细节
- 当子类继承了父类,并不是父类所有的属性和方法,都可以被子类访问, 子类只能访问父类的public 和 protected 属性和方法
举例:
说明结论
- 子类 可以访问 父类的 public 属性和方法 (不管是子类的内部,还是外部)
- 子类可以访问父类的protected 的属性和方法,但是必须在子类的内部才可以访问.
- 子类不能访问父类的private 的属性和方法
- 在输出子类对象时,我们dump 可以看到父类的私有属性,但是这个私有属性是输入父类,在子类中仍然无法访问
- 继承的本质(重点)
我们在理解继承的时候,应该这样理解:
- 不能理解成 子类把父类的属性和方法拷贝了一份
- 而是 子类和父类之间连接了一种查找的关系.
看一个示意图
- 继承的举例说明
代码说明:
- 关于继承查找的顺序和执行的说明
以Book 类 继承了 Goods 为例进行说明
- 当我们访问子类的某个属性或者方法时,首先先到子类中去查找是否有这个属性或者方法,如果有 在继续判断是否可以访问,如果可以访问就访问,如果不能访问,则报错.
- 当我们访问子类的某个属性或者方法时,首先先到子类中去查找是否有这个属性或者方法,如果没有, 就到该类的父类(如果有)去查找是否有这个属性或者方法,如果有,就继续判断是否可以访问,如果可以访问就访问,如果不能访问,就报错.
- 如果父类还有父类,则依次类推
9.6 继承的注意事项
- 子类最多只能继承一个父类(指直接继承)
举例:
- 子类可以继承其父类(或者基类)的 public ,protected修饰的变量(属性) 和 函数(方法)
案例看前面的即可.
- 在创建某个子类对象时,默认情况下会自动调用其父类的构造函数(指在子类没有自定义构造函数情况时)
- 如果在子类中需要访问其父类的方法(构造方法/成员方法 方法的访问修饰符是public/protected),可以使用父类::方法名(或者 parent::方法名 ) 来完成。
- 如果子类(扩展类)中的方法和父类(基类)方法相同,我们称为方法重写, 关于方法的重写我们在后面有详细的讲解
9.7 类定义的进一步完善
9.8 继承的课后练习题
9.9 方法重载
- 文档的说明
PHP所提供的"重载"(overloading)是指动态地"创建"类属性和方法。我们是通过魔术方法(magic methods)__call _callStatic来实现的
- 重载的英文 overloading
- php中,重载是值动态的创建属性和方法.
- 通过magic method 来实现
9.10传统的oop编程中,方法的重载指的是什么含义
- 介绍
在oop中,可以调用相同的函数名, 实现调用不同函数的结果,比如$obj->getSum($n1), $obj->getSum($n1, $2); 依靠函数不同的参数个数或者类型来区分不同函数.
举例:
在php中,不能像上面这样实现方法的重载.
9.11在php也可以实现方法重载,但是方式有变化(__call)
- 基本介绍: 在php中,也可以实现方法重载,使用魔术方法中的__call
- 代码说明:
看出(1) 方法重载不推荐使用, 但是有些项目中也有使用 (2) 面试笔试有人问你.
9.12课堂练习
9.13魔术方法__callStatic 说一下
当我们调用一个不可以访问(protected/private/不存在)的静态方法时,__callStatic魔术方法就会被系统调用。
举例说明:
9.14课后练习题
9.15属性的重载
- 基本介绍
当我们去给一个不存在的属性赋值时,类会自动的动态的创建一个对应的属性,这个属性是public 的.
- 对应属性重载的处理方式
- 程序员不干预,使用默认机制来处理.
- 禁止属性重载.
案例:
- 专门写一个数组属性和方法,来管理我们的重载的属性.
9.16方法的重写
- 看一个实际的问题
- 看一个案例
小结
- 当子类和父类的某个方法名一样时,我们就说子类的方法重写了父类的这个方法
- 重写(override), 有些文档手册把重写也叫做 覆盖, 在我们授课中,我们统计叫方法重写.
- 如果子类的方法重写父类的方法,要求方法名和参数个数完全一样,如果父类使用了类型约束,则子类的这个方法也必须有相同的类型.
9.17方法重写的细节说明
- 如果在子类中需要访问其父类的方法(public/protected),可以使用父类::方法名 或者 parent::方法名 来完成。
- 子类的方法的参数个数 ,方法名称,要和父类方法的参数个数,方法名称一样
- 如果父类的方法的参数使用了类型约束,还必须保证数据类型一致, 即子类的这个方法也需要使用相应的类型约束
- 子类方法不能缩小父类方法的访问权限(可以大于可以等于)
9.18属性的重写
- 基本的介绍: 属性也可以被重写,重写的几点注意事项
- 只有public 和 protected 的属性可以被重写
- 属性重写时,也不能缩小父类的属性控制访问
- 举例
9.19重写的课堂练习
9.20补充一个知识点类型约束
PHP 5 可以使用类型约束。函数的参数可以指定必须为对象(在函数原型里面指定类的名字),接口,数组(PHP 5.1 起)或者 callable(PHP 5.4 起)。不过如果使用 NULL作为参数的默认值,那么在调用函数的时候依然可以使用 NULL 作为实参。
举例说明一把:
第 10 章 多态[了解]
10.1基本介绍
所谓多态,就是在面向对象编程中,一个对象在不同的情况下的多种状态, 根据不同的上下文环境来决定。
- php本身就是天生的多态语言
- 当一个函数接收到不同对象时,会自动的判断并调用对应的方法.
- 多态利于类的维护和扩展
10.2举例说明
使用代码来完成上面的示意图:
10.3多态的课后练习题
晚上完成即可.
第 11 章 抽象类
11.1看一个开发的实际需求
当我们编写一个父类, 有个方法是不确定的,比如
class Animal {
public $name;
public function cry(){
echo '<br> 动物不知道怎么叫唤...';
}
}
cry 这里是不确定,写了也是白写, 没有意义,因此, oop中,可以将这样的方法做成抽象方法,类就做成抽象类.
11.2抽象类的基本概念
- 基本的概念
- 基本语法
11.3快速入门案例
- 抽象类主要用来被继承,偏重设计
- 当一个成员方法前使用abstract 来修饰,该方法就是抽象方法
- 当一个类名前有abstract来修饰,该类就是抽象类
11.4抽象类的细节讨论
- 抽象类不能实例化
- 抽象类可以没有abstract方法, 可以有非抽象方法和属性,常量
- 一旦类包含了abstract方法,则这个类必须声明为abstract 类
- 抽象方法不能有函数体
- 如果一个类继承了某个抽象类,则它必须实现该抽象类的所有抽象方法.(除非它自己也声明为抽象类)[多级继承]
11.5抽象类的最佳实践
抽象类的最大价值是设计,让其他的人来继承抽象类,并实现抽象方法.
11.6抽象类的课后练习
第 12 章 接口
12.1看一个实际的需求
12.2接口的基本介绍
- 所谓接口:就是将一些抽象方法封装到一起,在某个类需要使用时,只需要实现该接口就可以, 说的实现接口就是指将该接口中的所有的抽象方法都实现了。
- 基本语法
interface 接口名称{
常量;
方法;
}
几点说明
- interface 是关键字,不能够修改,规定好 。
- 接口名称有命名规范是: iXxxxXxxx , 首先以小写的i开头. 后面使用大驼峰命名规则
- 接口中的方法,都是抽象方法, 但是不需要使用abstract 去修饰
- 接口中,不能有普通的成员属性,但是可以有常量.
12.3使用接口的好处
12.4快速入门案例
12.5接口的最佳实践案例
- 使用接口的方式来模拟一下下面的运用场景
- 走代码
12.6接口的应用场景
总结: 当我们需要定义一些规范(方法)时,可以将这些方法封装到接口中 ,然后让其他的类来实现该接口即可.
12.7接口的细节讨论
- 接口不能被实例化
- 接口中所有的方法都不能有主体, 即接口中的方法都是抽象方法.
- 一个类可以实现多个接口,逗号隔开
举例说明:
- 接口中可以有属性,但只能是常量 ,默认是public, 但不能用public 显式修饰
- 一个接口不能继承其它的类,但是可以继承别的接口
12.8类定义的进一步完善
12.9继承类vs 实现接口
- 总结一下
- 实现接口可以看做是对php单继承机制的补充
- 实现接口可以在不打破继承的层级关系的前提下,对类的功能进行扩展
第 13 章 final关键字
13.1基本介绍
当程序员不希望某个成员方法被子类重写时,我们可以将该方法修饰为final 方法.
当程序员不希望某个类被继承,我们可以将该类修饰为final 类.
final "最终"
13.2基本语法
final 类名{
final 访问修饰符 function 方法名(){
//函数体
}
}
13.3快速入门案例
总结
- //如果我们不希望子类去重写attack方法, 使用final 修饰即可
- //如果我们不希望子类来继承某个类, 则使用final修饰该类即可
13.4final 的使用细节讨论
- final不能够修饰成员属性
- final 方法不能被重写,但可以被继承
- 一般来说,final 类中不会出现final 方法,因为final类都不能被继承,也就不会去重写override final类的方法了
- final 类 是可以被实例化的
第 14 章 类常量(const关键字)
14.1为什么需要使用当类常量
在某些情况下,程序员可能有这样的需求:
当不希望一个成员变量被修改,希望该变量的值是固定不变的。这时可以用const 去修饰该成员属性,这样这个属性就自动成为常量 , 比如所得税率, 数学中的圆周率等
14.2类常量的基本语法
类常量是在类中定义的.
class 类名{
const 常量名 = 初始值;
}
说明
- const 是关键字,规定好的而不能修改.
- 常量名的规范是 XXX_YYY , 全部大写,然后使用下划线间隔
- 类常量都是public , 但是我们不要使用public 去修饰.
14.3快速入门案例
//计算公司所得税的案例.
14.4关于类常量的使用细节说明
- 常量名一般字母全部大写 : TAX_RATE ,中间可以有下划线 TAX_RATE
- 在定义常量的同时,必须赋初值, 比如 const TAX_RATE=1.1
- const关键字前不能用public/protected/private修饰。默认是public
- 如何访问常量
在类的内部访问: 类名::常量名 self::常量名 接口::常量名
在类的外部访问: 类名::常量名 接口名::常量名
- 常量的值在定义的时候就初始化,以后就不能修改
- 常量可以被子类继承
- 一个常量是属于一个类的,而不是某个对象的
- 关于常量可以是什么数据类的讨论
结论: 常量可以是 基本数据类型(int, float , bool, string), 还是可以是 array ,但是不能是对象。
- 类常量可以在类中,类的外部和其它普通函数中使用
第 15 章 PHP面向对象编程的相关技术
基本: 把php面向对象编程的各个知识点都过一下.
15.1对象克隆技术和分析
15.2对象遍历[了解,应付笔试]
- 看看如何对对象进行遍历: 所谓对象的变量,指的是对某个对象的属性进行遍历.
- 举例
在类的外部对对象进行遍历, 这时我们只能遍历到对象的public 属性.
15.3php的内置标准类
看一个具体的需要: 如果,我们希望把一些数据,以对象的属性的方式存储,同时我们又不想定义一个类,可以考虑使用 PHP内置标准类 stdClass [standard标准]
php的内置标准类 stdClass , 这个是系统默认提供,不需要程序员去创建,而是直接使用就可以.
案例说明:
15.4数据类型转对象和对象转数组的说明
在我们的开发中,有时会看到有人将数组或者基本数据类转成对象,那么这个是怎么回事?
- 举例说明
15.5对象序列化和反序列化
- 基本介绍
所谓对象序列化是指: 将一个对象转换成一个字符串,这个字符串包括 属性名,属性值,属性类型, 和该对象对应的类名。简单的说明就把一个对象的数据和数据类型转成字符串.
- 看一个实际的需求
我要求同学们讲一个对象保存到文件中.(freeze 冷冻)-对象序列化.
- 反序列化
所谓反序列化就是指,将一个序列化的字符串,重新恢复成对应的对象.
说明
- 如果我们希望正确的操作反序列化对象,则需要引入该对象的类定义
- 对象序列化和反序列化的细节讨论
- 序列化的作用在哪些地方
- 对象序列化利于对象的保存和传输
- 可以让多个文件共享对象,而且我们将序列化后的对象保存到文件中,还可以达到在不同的时间段操作该对象.
- serialize() 函数会检查类中是否存在一个魔术方法 __sleep()。如果存在,该方法会先被调用,然后才执行序列化操作。此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组。如果该方法未返回任何内容,则
NULL
被序列化,并产生一个E_NOTICE
级别的错误。
代码说明:
- 与之相反, unserialize() 会检查是否存在一个 __wakeup()方法。如果存在,则会先调用 __wakeup 方法,预先准备对象需要的资源。
__wakeup() 经常用在反序列化操作中,例如重新建立数据库连接,或执行其它初始化操作。
代码说明:
15.6类与对象的相关函数
在面向对象编程中,有一系列的函数,可以来对类和对象以及成员方法进行操作。我们重点讲解5个,其它的函数就请同学们自己去看一下即可.
代码举例说明:
15.7traits 的讲解(重点)
- 看一个实际的需求
- 代码实现
- traits技术的细节说明
第 16 章 反射技术
16.1当我们echo $对象时,输出该对象的属性,成员方法等等信息
- 举例说明:
16.2反射机制的基本介绍
PHP 5 具有完整的反射 API,添加了对类、接口、函数、方法和扩展进行反向工程的能力。 此外,反射 API 提供了方法来取出函数、类和方法中的文档注释。
16.3反射机制的使用场景
- 写底层框架(比如tp框架有一个控制器调度原理)
- 扩展类的功能
- 管理大量的未知类
16.4看一个需求-一会我们一起搞定他
16.5我们看一个简单的案例-反向代理调用
- 使用反射机制代理带有某个对象的方法
- 代码说明
16.6反射机制的综合小练习-tp的控制器调度原理
走代码:
16.7反射练习
16.8小结:
文章来自泰牛PHP课堂笔记