0905作业
1. 编程: 匿名对象与匿名类的实现过程
实例
<?php /** * 匿名类: * 1. php 7.0+ 才支持 * 2. 类似于匿名函数,就是没有名称的类 * 3. 匿名类适合于一次性的创建与引用 * 4. 匿名类总是与: new 配套使用 */ echo'<h3>1. 编程: 匿名对象与匿名类的实现过程</h3>'; class Bigpighooves { private $name = '乾隆'; public function story($name) { return $this->name.'喜欢上了: <span style="color:red">'.$name.'</span>'; } } //有三种方式来访问 story() //1. 对象 $Bigpighooves = new Bigpighooves(); echo $Bigpighooves->story('富察皇后'), '<hr>'; //2.匿名对象 echo (new Bigpighooves())->story('魏璎珞'), '<hr>'; //3.匿名类 echo (new class { private $name = '乾隆'; public function story($name) { return $this->name.'喜欢上了: <span style="color:red">'.$name.'</span>'; } })->story('顺嫔'), '<hr>'; // 匿名类的三种应用场景 //1. 匿名类中可以使用构造方法 echo (new class ('海兰察'){ private $name; // 匿名类中的构造方法 public function __construct($name) { $this->name = $name; } public function story($name) { return $this->name.'喜欢上了: <span style="color:red">'.$name.'</span>'; } })->story('明玉'), '<hr>'; //2. 在匿名类中可以继承其它类中的成员 class KungFu { protected $kill; //招数 public function __construct($art='') { $this->kill = $art; } public function show() { return $this->kill ? : '黯然销魂掌'; } } echo (new class ('西门大官人',' ') extends KungFu { private $name; // 匿名类中的构造方法 public function __construct($name,$art='') { parent::__construct($art); $this->name = $name; } public function story($name) { return $this->name.'喜欢上了: <span style="color:red">'.$name.'</span>'; } public function show() { return $this->name.'的绝招是: '.'<span style="color:red">'.parent::show().'</span>'; } })->story('神仙姐姐'), '<hr>'; //3.可以在类声明中嵌套一个匿名类 class Anmal // 宿主类, 父类的角色 { public $name = '狗'; protected $color = '黑色'; private $type = '哈士奇'; protected function info () { return '售价3000元'; } public function demo1() { // 宿主类中的私有成员不能在匿名类中直接使用 // 可以通过在匿名类创建一个构造方法将宿主类中的私有成员进行注入 // 3. 将宿主类中的私有属性做为匿名类的构造方法的参数传入即可 return (new class ($this->type) extends Anmal { //1. 在匿名类中创建一个属性用来接收宿主类中的私有属性 private $type; //2. 创建一个构造方法 public function __construct($type) { $this->type = $type; } public function demo2() { return '我是嵌套匿名类中的方法: '. __METHOD__; } public function show() { return '动物的名称是: ' .$this->name. '<br>'. '动物的颜色是: ' .$this->color. '<br>'. '动物的种类是: ' .$this->type. '<br>'; } }); } } // 访问匿名类中的 demo2() echo (new Anmal())->demo1()->demo2(); echo '<hr>'; echo (new Anmal())->demo1()->show();
运行实例 »
点击 "运行实例" 按钮查看在线实例
2. 编程: Trait类的声明与工作原理
实例
<?php echo'<h3>2. 编程: Trait类的声明与工作原理</h3>'; /** * Trait 是什么东西? * 1.php 只能实现单继承,trait打破了限制,可以实现多继承 * 2.trait是一种代码复用技术,为PHP的单继承限制提供了一套灵活的代码复用机制(函 数, 类的继承)。 * 3.trait 使的类的语法,但不是类,所以不能实例化 * 4.triat 相当于方法集 * 5.Trait中属性的优先级,当前类>Trait>父类/基类 * 6.Trait的作用域,可以发现,Trait的作用域在引用该Trait类的内部是都可见的。 引用Trait时是在class内部使用的 * 可以理解为use关键字将Trait的实现代码Copy了一份到引用该Trait的类中 * 7. Insteadof和As关键字 */ //1.父类/基类 if (!class_exists('Person')) { class Person { protected $name; public function __construct($name='小明') { $this->name = $name; } public function study($course='php') { return $this->name . '在学习: ' . $course; } } } //2. 创建一个trait特性类里面有两个study方法, //分别是course的study方法,和Recreation的study方法 trait Course { public $frient = '小华'; public function study($name='踢足球') { return $this->name .'在学习'. $name; } } trait Recreation { public $friend = '小军'; public function study($name='打篮球') { return $this->name.'和'.$this->friend.$name; } } //3.当前类,因里面使用use关键字导入了trait的Course类,和Recreation类,并且使用insteadof和AS关键字 class Student extends Person { // use Course; // 导入了一个trait 类 // use Recreation; //use关键字的导入相当于将trait的Course类和trait的Recreation类copy了一遍到子类student里面 use Course, Recreation { Course::study insteadof Recreation; Recreation::study as MySport; } } $student = new Student(); //当前类中可以看出来trait的Course类优先级高于trait的Recreation类, //所以结果子类实例化的时候优先调用了Trait的Course类下面的study方法得到‘踢足球’ echo $student->study(), '<hr>'; //通过AS重命名之后,Recreation::study as MySport, //可以调用Mysport方法得到小明和小军打篮球 echo $student->MySport(), '<hr>';
运行实例 »
点击 "运行实例" 按钮查看在线实例
3. 编程: 类的自动加载函数的写法
实例
<?php echo'<h3>3. 编程: 类的自动加载函数的写法;</h3>'; //include './class/Demo1.php'; //include './class/Demo2.php'; //要点:spl_autoload_register()函数应该是主流框架使用最多的也是非常核心的函数之一, //可实现自动注册函数和类,实现类似autoload() 函数功能, //简化了类的调用与加载,提高了工作的效率 spl_autoload_register(function ($className) { require './class/'.$className.'.php'; //存在命名空间的情况下 // $className = str_replace("\\","/", $className); // require './class/'.$className.'.php'; }); echo Demo1::CLASS_NAME, '<hr>'; echo Demo2::CLASS_NAME, '<hr>';
运行实例 »
点击 "运行实例" 按钮查看在线实例
4.编程: 对象的序列化与反序列化的原理与应用
实例
<?php echo'<h3>4.编程: 对象的序列化与反序列化的原理与应用</h3>'; /** * 对象的序列化序列化是将对象状态转换为可保持或传输的格式的过程。 * 与序列化相对的是反序列化,它将流转换为对象。 * 这两个过程结合起来,可以轻松地存储和传输数据。 //$num = 500; //echo serialize($num),'<hr>'; // i:500; //$name = 'peter'; //echo serialize($name), '<hr>'; // s:5:"peter"; //$course = ['html','css','javascript']; //echo serialize($course), '<hr>'; // 1.自描述功能 关于成员对象,其实也是同一套子描述,这是一个递归的定义 自描述的功能主要是通过字符串记录对象和成员的名称来实现. 2.性能问题 序列化结果有协议头,协议头说明了类型,协议体则说明了类型所对应的值,并不会对序列化结果进行压缩. 2.序列化和反序列化中的魔术方法 魔术方法 __sleep和__wakeup */ class Db { //连接参数与返回值 public $db = null; public $host; public $user; public $pass; //构造方法 public function __construct($host='127.0.0.1', $user='root', $pass='root') { $this->host = $host; $this->user = $user; $this->pass = $pass; // 确保实例化对象的时候能自动连接上数据库 $this->connect(); } //数据库连接 private function connect() { $this->db=mysqli_connect($this->host,$this->user,$this->pass); } //对象序列化的时候自动调用 public function __sleep() { return ['host','user','pass']; } //反序列化: public function __wakeup() { $this->connect(); } } $obj = new Db(); /** * 对象序列化的特点: * 1. 只保存对象中的属性,不保存方法 * 2. 只保存类名,不保存对象名 */ //serialize通过这个接口我们可以自定义序列化和反序列化的行为, //这个功能主要可以用来自定义我们的序列化格式 echo serialize($obj),'<hr>'; $tmp = serialize($obj); var_dump(unserialize($tmp));
运行实例 »
点击 "运行实例" 按钮查看在线实例
补充:由于代码需要注释的太多,所以补充了一下:
4.问答: 对象的序列化与反序列化的原理与应用
对象的序列化与反序列化的原理与应用;
对象的序列化的原理:
魔术方法__sleep:用serialize() 函数实例化一个类的时候会检查类中是否存在一个魔术方法 __sleep()。
如果存在,该方法会先被调用,然后才执行序列化操作。此功能可以用于清理对象,
并返回一个包含对象中所有应被序列化的变量名称的数组。如果该方法未返回任何内容,
则 NULL 被序列化,并产生一个 E_NOTICE 级别的错误。
对象的序列化的应用:
__sleep() 方法常用于提交未提交的数据,或类似的清理操作。
同时,如果有一些很大的对象,但不需要全部保存,这个功能就很好用。
对象反序列化的原理:
魔术方法__wakeup:与serialize()相反,unserialize() 会检查是否存在一个 __wakeup() 方法。
如果存在,则会先调用 __wakeup 方法,预先准备对象需要的资源。
对象反序列化的应用:
__wakeup() 经常用在反序列化操作中,
例如重新建立数据库连接,或执行其它初始化操作。
5. 问答:谈谈你对面向对象编程的基本理解(不少于200字)
5问答:谈谈你对面向对象的基本理解。
面向对象编程是将数据和行为捆绑在一起的一种东西,是把一些属性和一些方法放在一个类里面,这些数据和行为被称之为类型的成员。我们可以创建类型的实例,不同的实例包含不同的数据,从而其表现出来的行为也会不同。面向对象有三大特性,封装、继承和多态。
封装使得类的成员得以有选择性的暴露,私有的属性(private)只可以在成员内部使用,受保护的属性(protected)可以被派生类型使用,公开的属性(public)可以被任何使用。封装隐蔽了对象内部不需要暴露的细节,使得内部细节的变动跟外界脱离,可以通过接口进行通信。
继承就是子类的一些特征是来源于父类的,对于一些公共的public,受保护的(protected)属性等非私有属性,可以继承父类的相关的属性,可以被子类重复使用,子类不必再在自己的类里面重新定义,对于自己类里面需要用到的新的属性和方法,子类就可以自己来扩展。
如果说封装和继承是为了使代码重用,那么多态则是为了实现接口重用。多态包含了重载和重写。重写很简单就是把子类从父亲类里继承下来的方法重新写一遍,父类里相同的方法就被覆盖了,当不同形参的情况,可以是形参类型不同或者形参个数不同,或者形参顺序不同。
总结一下,面向对象的特性提高了大型程序的重用性和可维护性.如果说封装和继承是面向对象的基础,那么多态则是面向对象最精髓的理论。掌握多态必先了解接口,只有充分理解接口才能更好的应用多态。