• 首页
  • 前端
    • HTML
    • CSS
    • Javascript
    • XML
    • AJAX
  • 前端框架
    • BootStrap
    • Jquery
  • PHP
    • 语法
    • 核心
    • 面向对象
    • PHP7
    • Socket
    • Swoole
  • 数据库
    • Mysql
    • Redis
    • Memcache
    • MongoDB
  • 优化
    • 优化方案
    • 页面静态化
    • Nginx
  • 后台框架与实战
    • Smarty
    • 源码Blog
    • TP3.2
    • TP3.2商城
    • TP5.0
    • TP5.0商城
    • Laravel
    • Laravel在线教育平台
    • Yii
    • Yii手机直播
    • CodeIgniter
    • Yaf
  • 移动开发
    • 微信公众号
    • 混合APP
  • 二次开发
    • DedeCMS
  • Linux
    • 基本操作
    • 环境搭建
  • 版本控制
    • GIT
    • SVN
  • Node.js
  • 资料库
没有结果
查看所有结果
  • 首页
  • 前端
    • HTML
    • CSS
    • Javascript
    • XML
    • AJAX
  • 前端框架
    • BootStrap
    • Jquery
  • PHP
    • 语法
    • 核心
    • 面向对象
    • PHP7
    • Socket
    • Swoole
  • 数据库
    • Mysql
    • Redis
    • Memcache
    • MongoDB
  • 优化
    • 优化方案
    • 页面静态化
    • Nginx
  • 后台框架与实战
    • Smarty
    • 源码Blog
    • TP3.2
    • TP3.2商城
    • TP5.0
    • TP5.0商城
    • Laravel
    • Laravel在线教育平台
    • Yii
    • Yii手机直播
    • CodeIgniter
    • Yaf
  • 移动开发
    • 微信公众号
    • 混合APP
  • 二次开发
    • DedeCMS
  • Linux
    • 基本操作
    • 环境搭建
  • 版本控制
    • GIT
    • SVN
  • Node.js
  • 资料库
没有结果
查看所有结果
没有结果
查看所有结果

面向对象编程(三)Clone、 foreach 遍历对象、 三私一公、 单例模式、 单例模式封装 MyPDO、 工厂模式、 序列化反序列化、 策略模式、 自动加载类、 迭代器、 魔术方法

Mr.Lee 由 Mr.Lee
2018年5月18日
在 PHP, 面向对象, 面向对象编程
0
面向对象编程(四)netbeans、 反射 Reflection、 命名空间、 异常处理、 类、 类别名
0
分享
1
浏览

面向对象编程(三)

回顾

  1. 多态:多种形态
  2. 多态分为:方法重载和方法重写

    1. 方法重写:之类重写了父类的同名方法

      1. 规则:

        1. 子类重写的方法必须和父类名字一样
        2. 可以具有不同个数的参数,但是严格标准必须是个数一样
        3. 子类中覆盖的方法不能比父类更加严格
    2. 方法重载:在同一个类中有多个同名的方法,通过不同的参数个数和参数类型区分不同方法。PHP不支持方法重载。
  3. 私有属性可以继承,但不能被重写
  4. 方法修饰符

    1. Static(静态的)

      1. Static可以修饰属性和方法
      2. 静态成员在加载类的分配空间
      3. 静态成员在内存中只有一份,属于类,不属于某个对象
      4. 通过类名来调用静态成员 类名::静态成员
      5. 静态成员也是可以被继承的
      6. Static也可以表示类名,表示调用当前方法对象的所属的类
    2. Final(最终的)

      1. Final修饰的方法不能被重写
      2. Final修饰的类不能被继承
    3. Abstract(抽象的)

      1. 只有方法的声明,没有方法的实现成为抽象方法
      2. 一个类中只要有一个方法是抽象方法这个类必须是抽象类
      3. 没有抽象方法的类也可以声明成抽象类
      4. 抽象类不可以被实例化,抽象方法必须在子类中重新实现
      5. 抽象方法是用来定义方法的命名规范的
  5. Self:总是表示当前类的类名
  6. 接口

    1. 如果一个类中所有的方法都是抽象类,这个类可以声明成接口
    2. 使用interface关键字
    3. 通过implements关键字实现接口
    4. 接口中所有的方法都是抽象的,公有的
    5. 不能使用abstract和final来修饰接口中的方法
    6. 类不允许多重继承,接口可以多种实现
  7. 类常量

    1. 使用const关键字声明
    2. Const常量可以放在类和接口中
  8. 参数约束:只能约束对象
  9. 父类可以指向子类的引用。

思考:如何实现C可以调用A和B中的方法


类的自动加载

在项目层面上类文件规则

  1. 一个文件中只能有一个类
  2. 文件名和类名同名
  3. 文件名以.class.php结尾

场景(一个文件中需要用到3个类)

  1. 创建Goods.class.php页面

<?php

//商品类

abstract class Goods {

protected $name;

final public function setName($name) {

$this->name=$name;

}

abstract function getName();

}

  1. 创建Book.class.php页面

<?php

//图书类

class Book extends Goods {

public function getName() { //重写了父类的方法

echo “《{$this->name}》<br>”;

}

}

  1. 创建Mobile.class.php

<?php

//手机类

class Mobile extends Goods {

public function getName() {

echo $this->name,'<br>’;

}

}

  1. 在PHP页面中使用上面的3个类

问题:在代码之前要引入需要的类。如果页面中需要用到很多的类,这样引入就很麻烦了。

类的自动加载

当页面执行的时候,通过PHP核心程序(zend engine)判断用户需要用到那个类,如果没有找到该类,就会自动调用__autoload()函数,并且以缺少的类名做为参数传递到__autoload()函数中,我们只要在__autoload()函数中加载需要的类即可。

通过缺少的类名加载类文件

在类文件保存地址规则的情况下使用

把类的地址映射到数组中然后加载

适合在类文件保存不规则的时候使用

clone和__clone()

clone:用来创建一个对象

__clone():当调用clone指令的时候自动执行__clone()函数

<?php

class Student {

//执行clone指令的时候自动调用__clone()方法

public function __clone() {

echo ‘你调用了clone指令<br>’;

}

}

header(‘Content-Type:text/html;charset=utf-8’);

$stu1=new Student;

$stu2=clone $stu1; //创建一个新的对象

var_dump($stu1);echo ‘<br>’;

var_dump($stu2);

总结:创建对象的方式:

  1. 实例化
  2. clone

单例模式

一个类只能创建一个对象

阻止类实例化的方法

  1. 抽象方法(可以阻止在类的外部和内部实例化)
  2. 私有的构造函数(阻止在类的外部实例化)

判断对象是否属于某个类

通过三私一公来实现

<?php

/**

*单例模式,三私一公

*/

class MySQL {

//保存MySQL的单例

private static $instance;

//阻止在类的外部实例化对象

private function __construct() {

}

//阻止在类的外部clone对象

private function __clone() {

}

//获取MySQL的单例

public static function getInstance() {

if(!self::$instance instanceof self) //静态属性中保存的对象是否属于MySQL类

self::$instance= new self(); //实例化对象对象

return self::$instance;

}

}

//测试

$db1=MySQL::getInstance();

$db2=MySQL::getInstance();

var_dump($db1); // object(MySQL)#1 (0) { } 

echo ‘<br>’;

var_dump($db2); // object(MySQL)#1 (0) { } 

项目层面的单例模式

多个对象的单例

工厂模式

传递不同的参数,返回不同的对象

<?php

class ProductA {

public function show() {

echo ‘获取A商品<br>’;

}

}

class ProductB {

public function show() {

echo ‘获取B商品<br>’;

}

}

//工厂模式(传递不同的参数获取不同的对象)

class Factory {

public static function create($num) {

switch($num%2) {

case 1:

return new ProductA();

case 0:

return new ProductB;

}

}

}

//测试

header(‘Content-Type:text/html;charset=utf-8’);

$objA=Factory::create(10);

$objB=Factory::create(15);

$objA->show(); //获取B商品

$objB->show(); //获取A商品

策略模式

传递不同的参数调用不同的策略(方法)

<?php

class Walk {

public function method() {

echo ‘走着去学校<br>’;

}

}

class Bus {

public function method() {

echo ‘坐车去学校<br>’;

}

}

class Bike {

public function method() {

echo ‘骑车去学校<br>’;

}

}

//策略模式,传递不同的对象,调用不同的方法

class Strategy {

public function go($obj) {

$obj->method();

}

}

//测试

header(‘Content-Type:text/html;charset=utf-8’);

$strategy=new Strategy();

$strategy->go(new Walk()); //走着去学校

$strategy->go(new Bus()); //坐车去学校

$strategy->go(new Bike()); //骑车去学校

魔术方法

已经学过的魔术方法

__construct():构造函数,当实例化对象的时候自动调用

__destruct():析构函数,当对象销毁的时候自动调用

__clone():当调用clone指令的时候自动调用

__toString()和__invoke()

__tostring():当对象作为字符串使用的时候自动执行

__invoke():当将对象作为函数使用的时候自动执行

__set()、__get()、__isset()

1、__set($key,$value):当给无法访问的属性赋值的时候自动调用

2、__get($key):当给无法访问的属性取值的时候自动调用

3、__isset($key):当判断无法访问的属性是否存在

4、__unset($key):当销毁无法访问的属性的时候自动调用

总结:给私有属性赋值的方法

  1. 通过公有的方法给私有属性赋值
  2. 通过构造函数给私有属性赋值
  3. 通过魔术方法__set()赋值,__get()取值

<?php

class Student {

private $name;

private $age;

/**

*当给无法访问的属性赋值的时候自动调用

*@param $key string 属性名

*@param $value string 属性值

*/

public function __set($key,$value) {

if($key==’age’ && !($value>=20 && $value<=30)){

echo ‘年龄必须在20~30之间<br>’;

return;

}

$this->$key=$value;

}

/**

*当给无法访问的属性取值的时候自动调用

*@param $key string 属性名

*/

public function __get($key) {

return $this->$key;

}

/**

*当判断无法访问的属性是否存在

*/

public function __isset($key) {

return isset($this->$key);

}

/**

*当销毁无法访问的属性的时候自动调用

*/

public function __unset($key) {

unset($this->$key);

}

}

header(‘Content-Type:text/html;charset=utf-8’);

$stu=new Student;

$stu->name=’tom’; //给私有属性赋值

$stu->age=25;

echo ‘姓名:’.$stu->name,'<br>’; //获取私有属性的值

echo ‘年龄:’.$stu->age,'<br>’;

var_dump(isset($stu->name)); //判断私有属性是否存在

echo ‘<br>’;

unset($stu->name); //销毁私有属性

var_dump($stu);

__call()、 __callStatic()

<?php

class Student {

/**

*当调用无法访问的属性的时候自动调用

*@param $name string 方法名

*@param $args array 参数数组

*/

public function __call($name,$args) {

echo “对象中没有'{$name}’的方法<br>”;

echo ‘你传递”‘.implode(‘,’,$args).'”参数给我也没用<hr>’;

}

/**

*当调用无法访问的静态方法的时候自动调用

*/

public static function __callstatic($name,$args) {

echo “对象中没有'{$name}’这个静态方法<br>”;

echo ‘你传递”‘.implode(‘,’,$args).'”参数给我也没用<hr>’;

}

}

header(‘Content-Type:text/html;charset=utf-8’);

$stu=new Student;

$stu->show(10,20); //调用无法访问的方法

Student::connect(); //调用无法访问的静态方法

__sleep()和 __wakeup()

__sleep():在序列化的时候自动调用

__wakeup();在反序列化的时候自动调用

<?php

class Student {

private $name;

private $sex;

private $add;

/**

*在调用serialize时候自动调用

*作用:只保留需要序列化的属性

*/

public function __sleep() {

return array(‘name’,’sex’); //返回需要序列化的属性

}

/**

*在调用unserialize时候自动调用

*作用:初始化对象的值

*/

public function __wakeup() {

$this->name=’tom’;

$this->sex=’男’;

$this->add=’中国’;

}

}

header(‘Content-Type:text/html;charset=utf-8’);

$stu=new Student;

$str=serialize($stu);

echo $str,'<hr>’;

$stu=unserialize($str);

print_r($stu);

序列化(serialize)和反序列化(unserialize)

思考:能否将数组和对象永久保存?

答:可以,但是必须先序列化

序列化就是将数组或对象变成一个字符串序列

数组序列化和反序列化

序列化

反序列化

对象序列化和反序列化

序列化

反序列化

发现可以反序列化,但是类名没有反编译出来,解决方法在反序列化之前引入对应的类就可以了

foreach遍历对象

foreach遍历只能遍历到可以访问到的属性

迭代器(Iterator)

场景:一个班级有60个学生,如何遍历这个班?

解决:

Iterator是PHP内置的接口,定义了5个抽象方法,只要实现了这5个抽象方法,迭代器就可以工作了。

例题

<?php

//班级类

class MyClass implements Iterator {

private $list=array(‘tom’,’berry’,’ketty’,’rose’); //学生数组

//复位数组

public function rewind() {

reset($this->list);

}

//判断当前指针是否有效

public function valid() {

return key($this->list)!==null;

}

//返回当前键

public function key() {

return key($this->list);

}

//返回当前值

public function current() {

return current($this->list);

}

//指针下移

public function next() {

next($this->list);

}

}

//测试

$class=new MyClass();

foreach($class as $key=>$val) {

echo $key,’-‘,$val,'<br>’;

}

通过单例模式封装MySQL数据库操作类

实现功能

  1. 连接数据库
  2. 查询数据

需要注意的点:

  1. 一个方法只实现一个功能,方法的功能越单一越好,这样可以最大限度的实现代码的可重用性。

代码

<?php

/**

*MySQL数据库操作类(单例模式实现)

*/

class MySQLDB {

private $host; //主机地址

private $port; //端口号

private $user; //用户名

private $pwd; //密码

private $dbname; //数据库名称

private $charset; //支付编码

private static $instance; //保存MySQLDB的实例

//阻止在类的外部实例化

private function __construct($config) {

$this->initParam($config);

$this->connect();

$this->selectDb();

$this->setCharSet();

}

//阻止在类的外部调用clone指令

private function __clone() {

}

//获取MySQLDB类的单例

public static function getInstrance($config=array()) {

if(!self::$instance instanceof self)

self::$instance=new self($config);

return self::$instance;

}

//初始化数据

private function initParam($config) {

$this->host=isset($config[‘host’])?$config[‘host’]:’127.0.0.1′;

$this->port=isset($config[‘port’])?$config[‘port’]:’3306′;

$this->user=isset($config[‘user’])?$config[‘user’]:”;

$this->pwd=isset($config[‘pwd’])?$config[‘pwd’]:”;

$this->dbname=isset($config[‘dbname’])?$config[‘dbname’]:’data’;

$this->charset=isset($config[‘charset’])?$config[‘charset’]:’utf8′;

}

//连接数据库

private function connect() {

if(!$link=@mysql_connect(“{$this->host}:{$this->port}”,$this->user,$this->pwd))

$this->showMessage();

}

//选择数据库

private function selectDb() {

if(!mysql_select_db(“$this->dbname”))

$this->showMessage();

}

//设置字符编码

private function setCharSet() {

if(!@mysql_query(“set names {$this->charset}”)){

$this->showMessage();

}

}

//显示错误的方法

private function showMessage($sql=”) {

if($sql!=”)

echo ‘错误SQL语句:’.$sql,'<br>’;

echo ‘错误信息:’.mysql_error(),'<br>’;

echo ‘错误编号:’.mysql_errno(),'<br>’;

exit;

}

//执行SQL语句的方法

private function query($sql) {

if($rs=mysql_query($sql))

return $rs;

$this->showMessage($sql);

}

//拼接函数名

private function createFunction($type) {

$allow=array(‘assoc’,’row’,’array’);

if(!in_array($type,$allow))

$type=’assoc’;

return ‘mysql_fetch_’.$type;

}

//获取二维表的数据

public function getAll($sql,$type=’assoc’) {

$fn=$this->createFunction($type);

$rs=$this->query($sql);

$array=array();

while($rows=$fn($rs)) {

$array[]=$rows;

}

return $array;

}

}

header(‘Content-Type:text/html;charset=utf-8’);

//测试

$config=array(

‘user’ => ‘root’,

‘pwd’ => ‘root’,

‘dbname’=> ‘jokedb’,

);

$mysql=MySQLDB::getInstrance($config);

$rs=$mysql->getAll(‘select * from title’,’aa’);

echo ‘<pre>’;

var_dump($rs);

标签: Cloneforeach 遍历对象三私一公单例模式单例模式封装 MyPDO工厂模式序列化反序列化策略模式自动加载类迭代器魔术方法
上一篇文章

面向对象编程(四)netbeans、 反射 Reflection、 命名空间、 异常处理、 类、 类别名

下一篇文章

面向对象(二)分页、 多态、 封装、 接口、 方法修饰符、 方法重写、 方法重载、 类常量、 继承

下一篇文章
面向对象编程(四)netbeans、 反射 Reflection、 命名空间、 异常处理、 类、 类别名

面向对象(二)分页、 多态、 封装、 接口、 方法修饰符、 方法重写、 方法重载、 类常量、 继承

发表回复 取消回复

您的邮箱地址不会被公开。 必填项已用 * 标注

Search

没有结果
查看所有结果

About Me

个人随笔

Winston Lee

Programmer

Hello & welcome to my blog! My name is Winston Lee and am a programmer and am keen on sharing.

Winston Lee

About Me

Hello & welcome to my blog! My name is Winston Lee and am a programmer and am keen on sharing.

Categories

  • AJAX
  • BootStrap
  • CodeIgniter
  • CSS
  • DedeCMS
  • GIT
  • HTML
  • Javascript
  • Jquery
  • Laravel
  • Laravel在线教育平台
  • Linux
  • Memcache
  • MongoDB
  • MVC
  • Mysql
  • Nginx
  • Node
  • PDO
  • PHP
  • PHP7
  • PHP基本语法
  • PHP核心编程
  • Redis
  • Smarty
  • Socket
  • SVN
  • Swoole
  • TP3.2
  • TP3.2商城
  • TP5.0
  • TP5.0商城
  • XML
  • Yaf
  • Yii
  • Yii手机直播
  • 二次开发
  • 优化方案
  • 前端技术
  • 前端框架
  • 后台框架
  • 基本操作
  • 微信公众号
  • 数据库
  • 未分类
  • 混合APP
  • 源码Blog项目
  • 版本控制
  • 环境搭建
  • 移动端开发
  • 网站优化
  • 资料
  • 面向对象
  • 面向对象编程
  • 页面静态化

Tags

DOM Json RBAC 事件 传参 函数 分页 判断语句 匿名函数 变量 图片上传 存储过程 安装 对象 封装 属性 接口 控制器 数据库操作 数据类型 数据表 数组 文件上传 无刷新分页 权限 标签 模型 正则 流程控制 目录结构 算法 类 索引 继承 缩略图 表关系 视图 路由 运算符 选择器 递归 配置 错误处理 页面静态化 验证码
  • 首页
  • 前端
  • 前端框架
  • PHP
  • 数据库
  • 优化
  • 后台框架与实战
  • 移动开发
  • 二次开发
  • Linux
  • 版本控制
  • Node.js
  • 资料库

沪公网安备31011502400873 | 沪ICP备2024050435号-3

没有结果
查看所有结果
  • 首页
  • 前端
    • HTML
    • CSS
    • Javascript
    • XML
    • AJAX
  • 前端框架
    • BootStrap
    • Jquery
  • PHP
    • 语法
    • 核心
    • 面向对象
    • PHP7
    • Socket
    • Swoole
  • 数据库
    • Mysql
    • Redis
    • Memcache
    • MongoDB
  • 优化
    • 优化方案
    • 页面静态化
    • Nginx
  • 后台框架与实战
    • Smarty
    • 源码Blog
    • TP3.2
    • TP3.2商城
    • TP5.0
    • TP5.0商城
    • Laravel
    • Laravel在线教育平台
    • Yii
    • Yii手机直播
    • CodeIgniter
    • Yaf
  • 移动开发
    • 微信公众号
    • 混合APP
  • 二次开发
    • DedeCMS
  • Linux
    • 基本操作
    • 环境搭建
  • 版本控制
    • GIT
    • SVN
  • Node.js
  • 资料库

沪公网安备31011502400873 | 沪ICP备2024050435号-3