批改状态:合格
老师批语:不建议将多天作业合并完成的, 不方便核对完成情况, 下次注意, 不过写得不错
近期学习了面向对象编程中一些比较抽象的概念,在此对部分重点内容的要点做一下整理小结。
1、类的继承,也叫类的扩展(父类: 基类、子类: 扩展类)
二类成员: 子类有权访问的父类成员类型, public, protected
三种操作: 子类对父类的三种操作: 继承, 重写, 扩展
2、抽象类: 部分分离了设计(抽象类中完成)与实现(工作类中完成)
设计类:具体方法,有方法体: {…};抽象方法:没有方法体,
只要一个类中有一个抽象方法, 那么这个类就是:抽象类
实现类/工作类: 是一个可以被实例化的普通类,最终工作类: 允许实例化
工作类不一定是可以被实例化的普通类,也可是一个抽象类
抽象类也可以被继承, 抽象类也可以用在继承的上下文环境中
抽象类中允许有抽象成员, 但不是强制的,也可以没有。
必须将抽象类中的抽象方法实现
3、接口: 完全分离了”设计与实现”,关键字: interface,
使用与类相似的语法: 抽象方法, 常量, 构造方法(魔术方法的一种),
默认访问控制必须是public,接口允许多继承, 从而间接实现了PHP的多继承,implements (英婆慢吃),单接口, 工作类实现接口 接口常量的访问与类常量一样。多接口继承,一个接口同时继承多个接口,接口可以突破php类的继承限制, 允许多继承, 形成了多层级的接口。
用抽象类来部分实现一个接口,接口是实现多态的重要手段。
因为是面向接口编程, DB_PDO, DB_MySQLi都实现了同一接口,只要将对象参数的类型限定在接口上就可以实现多态,至于选用哪个类实例,由用户自行选择。
4、trait: php5.4+, 代码复用,与抽象类,接口一样不能实例化, 只能嵌入到宿主类中使用,它是一个特殊类: 1. 常规, 2. 静态, 3. 抽象, 不能用类常量。
类中使用trait , 用use 关键,将use tDemo理解为加载。
trait 功能1: 代码复用;trait2: 在继承上下文环境中, 具有优先级, 通过优先的设置, 降低单继承的影响。
trait中的同名方法将父类中同名方法覆盖了, 重写了;当前类的同名方法又会覆盖掉trait中同名方法;方法使用的优先级:子类 > trait > 父类。Trait组合的同名方法的命名冲突的解决方案:一是替换,用关键字insteadOf,二是别名,用关键字as,as 还可以修改trait成员的访问控制。
1、实例演示后期静态绑定的原理与实现
<?php// 后期静态绑定: 又叫延迟静态绑定// 后期静态绑定工作在: 静态继承上下文的环境中abstract class CreateInstance{}// 实现类1class User extends CreateInstance{public static function create() : self{return new self();}}// 实现类2class Product extends CreateInstance{public static function create() : self{return new self();}}// 客户端$user = User::create();var_dump($user);echo '<hr>';$product = new Product();var_dump($product);----------------------// 将demo1.php中的代码进行简化, 将类实例的创建过程上移到它的基类中abstract class CreateInstance{public static function create(){// 出错原因: self 代表当前类,而当前是抽象类, 不能实例化, 不能用new 调用// 解决:将类的定义与类的调用完全分离开// 方案: 后期静态绑定, 使用关键字: static, 将self 替换掉// return new self();return new static();// 程序执行有二个过程: 编译, 执行// 类方法与有一个调用上下文, 定义上下文// self: self始终与定义该方法(属性)的类进行绑定// static: static总是自动与该方法(属性)调用类进行绑定// self: 与定义类绑定// static: 与调用类绑定}}// 实现类1class User extends CreateInstance{}// 实现类2class Product extends CreateInstance{}// 客户端$user = User::create();var_dump($user);echo '<hr>';$product = Product::create();var_dump($product);---------------------// 后期静态绑定的应用场景: 动态绑定静态成员的调用上下文// 调用上下文者: 调用者class Base{// 静态方法: 允许重写public static function index(){return '当前调用方法: ' . __METHOD__;}public static function fetch(){// return self::index();return static::index();}}class User extends Base{// 重写父类中的静态方法: index()public static function index(){return '当前调用方法: ' . __METHOD__;}}// 客户端// echo Base::fetch();echo User::fetch();
2、魔术方法之构造方法与析构方法
<?php// 魔术方法:// 语法: 类中有一些方法总是使用双下划线开头, 这就叫魔术方法// 调用者: 由系统根据一定的条件或用户行为, 自动调用/触发, 禁止用户主动调用// 构造方法: __construct(), 是类的实例化过程中被自动调用, new 的时候class Scorelist{private $course;private $score;// 在实例化的时候,自动完成类属性的初始化/赋值,如何做到呢?// 构造方法: 构造器, 功能就是生成一个新对象public function __construct($course, $score){// 1. 生成一个新对象/类实例// $this是由php接管的对象, 不能用户设置, 下面是伪代码,辅助理解// $this = new self();// 2. 初始化这个新对象: 给这个新对象添加属性并赋值, 或自动执行某些操作方法$this->course = $course;$this->score = $score;$this->write();// 3. 返回这个刚刚创建并初始化的对象// 隐式返回当前新生的类实例, 不用显式返回, 自动完成// return $this;}// 类方法public function write(){echo "$this->course : $this->score 分<hr>";}// 析构方法, 没有参数, 销毁/删除一个对象的时候调用public function __destruct(){echo "Destroying " . $this->score ;}}// 客户端$Scorelist1 = new Scorelist('PHP网络编程', 90);//var_dump($Scorelist1);
3、实例演示属性重载/拦截器的所有方法
<?php// 重载: php中的重载与其它语言不同(C++/Java), 称为"访问拦截器"更贴切// 拦截器: 属性拦截器, 方法拦截器// 使用场景: 当用户访问一个不存在的或无权限访问属性/方法时, 自动调用// 访问: 包括二个操作:就是读和写, 或者称为: 查询和设置// 属性拦截器: __set(), __get(), __isset(), __unset()class Product{private $name;private $price;private $taxRate = 0.06;public function __construct($name, $price){$this->name = $name;$this->price = $price;}// 1. 属性查询拦截器public function __get($property){// return $this->$property;// return $property === 'name' ? $this->name : '无权访问';// 拦截转发器// 1. 先事先约定一些方法专用于处理属性访问$method = 'get' . ucfirst($property);// 2. 转发访问请求return method_exists($this, $method) ? $this->$method() : null;}private function getName(){return mb_substr($this->name, 0, 5) . '...';}private function getPrice(){return $this->price + $this->price * $this->taxRate;}// 2. 属性设置拦截器public function __set($property, $value){$method = 'set' . ucfirst($property);// 转发访问请求return method_exists($this, $method) ? $this->$method($value) : null;}private function setName($value){$this->name = trim($value);}private function setPrice($value){if ($value === null) unset($this->price);else $this->price = $value * (1-$this->taxRate);}// 3. 属性检测拦截器public function __isset($property){return $property === 'name' ? isset($this->name) : false;}// 4. 属性销毁拦截器public function __unset($property){if ($property === 'price') {$method = 'set' . ucfirst($property);// 转发访问请求if (method_exists($this, $method)) return $this->$method(null) ;}}}// 客户端$product = new Product('一坛绍兴女儿红',520);// 访问了一个无访问权限的类属性echo $product->name;echo $product->price;echo '<hr>';$product->name = '一辆8手的夏利';$product->price = 2000;echo $product->name;echo $product->price;echo '<hr>';echo isset($product->name) ? '存在' : '不存在';echo isset($product->price) ? '存在' : '不存在';unset($product->name);echo $product->name;unset($product->price);echo $product->price;
4、实例演示方法重载/拦截器的所有方法
<?php// 方法拦截器, 其实比属性拦截器更有用// __call(), __callStatic()class User{// 方法拦截器public function __call($name, $arguments){printf('方法名: %s , 参数: [%s]', $name, implode(', ', $arguments));}// 静态方法拦截器public static function __callStatic($name, $arguments){printf('静态方法名: %s , 参数: [%s]', $name, implode(', ', $arguments));}}$user = new User();$user->demo(1,2,3,4);echo '<br>';User::demo(6,7,8,9);
本次课程老师从浅显易懂的实例出发,详解介绍了静态绑定与拦截器相关内容,通过回看视频及讲义代码,加深了理解, 并通过修改实现部分代码,同时对前期学习的内容作了阶段性的回顾和整理,感觉非常有必要。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号