静态延迟绑定
在未使用静态延迟绑定的时候,如果父类使用self时,子类继承了父类,在子类中重新赋值的时候,是继承父类的,也可以说是不生效的,但是在父类将self更改为static时,将改为延时绑定模式,开启延时绑定模式时,子类在重新赋值时,子类已延时绑定,最终的结果将是子类的结果。
### 单例模式
单例模式感觉是在数据库链接的时候经常用到,意思就是先设置一个静态属性,这个静态属性使用这个静态方法,静态方法内判断静态属性是否进行了实例化,如果没有进行实例化,就进行实例化一次,在子类中使用时,防止父类中已经调用(实例化了一次了),并不会在子类中重新调用时,需要将静态属性在子类中重新赋值,或者重新调用一遍,让他为空即可。

  1. <?php
  2. /**
  3. *
  4. * 后期静态绑定 延迟静态绑定 static
  5. *
  6. */
  7. /**
  8. * 在创建类层次结构时,self关键字在编译时就已经确定了他的作用域范围,而不是在运行时(后期),
  9. * self不能动态的与调用类进行绑定,我们后期(延迟)静态绑定
  10. *
  11. * $this能动态的与调用类进行绑定。
  12. *
  13. */
  14. class Employee
  15. {
  16. public static $favSport = 'football';
  17. public static function watchTV()
  18. {
  19. echo 'watching ' . static::$favSport . '<br>';
  20. }
  21. }
  22. class Execute extends Employee
  23. {
  24. public static $favSport = 'polo';
  25. }
  26. echo Execute::watchTV();
  27. echo Execute::$favSport;
  28. // 延迟绑定时将 输出的部分,也就是最终的部分 self替换static
  29. class tbody
  30. {
  31. public $favSsport = 'football';
  32. public function ccTV()
  33. {
  34. echo 'cctv' . $this->favSsport . '节目';
  35. }
  36. }
  37. class td extends tbody
  38. {
  39. public $favSsport = '2';
  40. }
  41. $a = new td;
  42. $a->ccTV();
  43. // 非静态类既不需要进行延迟绑定,他是调用最终的部分
  44. //单例模式 只允许类被实例化一次
  45. class Father
  46. {
  47. // 将构造器设置成私有的
  48. private function __construct()
  49. {
  50. }
  51. private function __clone()
  52. {
  53. }
  54. // 设置一个受保护的属性 存储father类的实例
  55. protected static $_instance;
  56. // 获取father类的实例 唯一实例
  57. // static function getInstance()
  58. // {
  59. // if (self::$_instance === null)
  60. // // 将值赋值给静态属性
  61. // self::$_instance = new self;
  62. // // 返回的是一个对象
  63. // return self::$_instance;
  64. // }
  65. // }
  66. /////////////下面更改为延迟绑定//////////////
  67. static function getInstance()
  68. {
  69. if (static::$_instance === null)
  70. // 将值赋值给静态属性
  71. static::$_instance = new static;
  72. // 返回的是一个对象
  73. return static::$_instance;
  74. }
  75. }
  76. class son extends Father
  77. {
  78. protected static $_instance;
  79. }
  80. var_dump(Father::getInstance());
  81. var_dump(son::getInstance());
  82. // 自己的见解,单例模式只允许实例化一次,其实就是在var_dump第一次执行的时候,已经执行了一次静态延迟绑定,所以在第二次调用子类的时候,
  83. // 实际上父类就已经调用一次了,所以在if判断分支的时候,并不会进入static::$_instance === null,而是跳过,直接输出结果,如果想他
  84. // 继续执行一次,需要在子类中,重新给static::$_instance === null赋值为空,也就是重新定义一次

单例模式链接数据库(非延迟静态)
单例链接(数据库操作链接演示,操作其他也类似)其实是将数据库的增删改查链接数据库封装到接口中,封装到接口中后,后面的由抽象类来完成一部分的工作,工作类也就是普通类继承一部分抽象类来完成所有的工作,接口提供一个方法,抽象类完成一个最主要的部分,工作类来完成所有的工作,下面的工作类都的 where判断感觉也可以直接写到类的里面,还没有测试,等测试下,完成了所有的类方法后封装成类属性或者方法,直接可以在最后进行调用

代码部分:

  1. <?php
  2. /***
  3. * 单例模式链接数据库 应用程序跟设计库交互
  4. *
  5. */
  6. namespace app\laolu;
  7. use PDO;
  8. interface idbBase
  9. {
  10. ///增删改查
  11. //插入
  12. static function insert($db, $data);
  13. //查询
  14. static function select($db, $where = []);
  15. // 更新
  16. static function update($db, $where = []);
  17. //删除
  18. static function delete($db, $data, $where = []);
  19. //数据库链接
  20. static function doconnect($dsn, $user, $password);
  21. }
  22. abstract class adb implements idbBase
  23. {
  24. private static $_instance;
  25. private function __construct()
  26. {
  27. }
  28. private function __clone()
  29. {
  30. }
  31. static function doconnect($dsn, $user, $password)
  32. {
  33. //创建adb类的唯一实例 获取唯一的pdo对象
  34. if (is_null(self::$_instance)) {
  35. self::$_instance = new PDO($dsn, $user, $password);
  36. }
  37. return self::$_instance;
  38. }
  39. }
  40. //工作类
  41. class Db extends adb
  42. {
  43. ///增删改查
  44. //插入
  45. static function insert($db, $data)
  46. {
  47. }
  48. //查询
  49. // static function select($db, $where = [])
  50. // {
  51. // $dbo = $db->query("SELECT * FROM `mj_user` LIMIT 3")->fetchAll(PDO::FETCH_ASSOC);
  52. // return $dbo;
  53. // }
  54. static function select($db, $where = ['uid' => 1])
  55. {
  56. foreach ($where as $key => $value) {
  57. $sql = $key . '>' . $value;
  58. // 组装循环条件 这里装成字符后再query语句里面填入where循环条件
  59. }
  60. $dbo = $db->query("SELECT * FROM `mj_user` WHERE " . $sql . " LIMIT 3")->fetchAll(PDO::FETCH_ASSOC);
  61. return $dbo;
  62. }
  63. // 更新
  64. static function update($db, $where = [])
  65. {
  66. }
  67. //删除
  68. static function delete($db, $data, $where = [])
  69. {
  70. }
  71. }
  72. $config = [
  73. 'type' => $type ?? 'mysql',
  74. 'host' => $host ?? 'localhost',
  75. 'dbname' => $dbname ?? 'ad',
  76. 'username' => $username ?? 'root',
  77. 'password' => $password ?? 'H9MvYSqY3JmAC4aj',
  78. 'port' => $port ?? '3306',
  79. 'charset' => $charset ?? 'utf8'
  80. ];
  81. extract($config);
  82. $dsn = sprintf('%s:host=%s;port=%s;charset=%s;dbname=%s', $type, $host, $port, $charset, $dbname);
  83. $pdo = Db::doconnect($dsn, $username, $password);
  84. $db1 = Db::select($pdo);
  85. var_dump($db1);
  86. var_dump(Db::select($pdo));
  87. // foreach ($db1 as $key => $value) {
  88. // echo $key
  89. // }

重载就是php类中无该类属性成员(或私有属性)时,将自动创建类属性成员,也就是通过_set方法来创建的类属性成员,当访问这个属性是,使用的魔术方法__get 方法来访问这个类成员,类属性重载是将新类属性成员通过set get魔术方法来新建类属性,但魔术方法都是公开的,所以新建的类属性成员,私有属性成员都成为公开成员,违反了也忘了叫啥了。

  1. <?php
  2. /**
  3. * php重载 overload
  4. * php重载 方法拦截器 是指动态的创建类属性和方法,我们是通过魔术方法 来实现的, _get _set _callstatic _call
  5. *
  6. * 当访问类中不存在或者不可见成员时,会自动调用魔术方法__set __get
  7. * 因为魔术方法都是公开的,所以一些私有成员的不可见性就不会生效
  8. *
  9. */
  10. class Credit
  11. {
  12. public $name;
  13. private $idNum;
  14. public function __construct($name, $idNum)
  15. {
  16. $this->name = $name;
  17. $this->idNum = $idNum;
  18. var_dump($this->idNum);
  19. echo "<br>上面输出了<br>";
  20. }
  21. public function __set($name, $value)
  22. {
  23. // echo '<hr>';
  24. // echo $name . '<br>';
  25. // echo $value . '<br>';
  26. $this->$name = $value;
  27. // var_dump($this->$name);
  28. echo '<br>521314php<br>';
  29. return $this->$name;
  30. }
  31. public function __get($name)
  32. {
  33. return $this->$name;
  34. }
  35. }
  36. $a = new Credit('胡歌', '341621199905015488');
  37. echo $a->name;
  38. echo '<hr>';
  39. $ab = $a->name;
  40. echo $ab . '这里输出了<br>';
  41. $a->age = 20; //__set
  42. echo $a->age; //__get
  43. // echo $a->name;
  44. echo $a->idNum;//私有属性是通过__get魔术标签输出的

重载的私有属性或新类成员方法时解决方法:
在私有属性新赋值时,也是走的set 在进入set方法自动调用时,将set方法return出去的数据拦截,拦截组装出一个新的私有类成员方法,将在私有方法中输出结果,这样就将私有属性继续私有化,并不会公开化,当echo输出时,使用的__get魔术方法,但是传入的值,只是属性名,同样也是将属性私有化处理,新建一个私有方法,在get魔术方法中组装一个私有类成员方法
在下面使用中的新函数:

函数名函数说明使用方法
ucfirst()将传入的值首字母大写ucfirst($name)传入的name值将首字母大写处理
method_exists()检查本作用域中是否有这个类成员方法method_exists($this, $method) $this是本作用域,$method检查的变量
property_exists()检查本类方法中是否存在这个类成员,属性类成员property_exists($this, $name)前面是作用域,后面是检查的类成员
  1. <?php
  2. class Credit
  3. {
  4. private $name;
  5. private $idNum;
  6. public function __construct($name, $idNum)
  7. {
  8. $this->name = $name;
  9. $this->idNum = $idNum;
  10. }
  11. //下面设置了一个私有的方法 这里的set相当于一个中转站
  12. public function __set($name, $value) //name是拦截的属性的名,value是拦截的属性的值
  13. {
  14. // $this->$name = $value;
  15. // return $this->$name; //这里将返回的属性值取消,暂时先不return出去
  16. // 拼接实际调用的方法名称 ucfirst是将函数的第一个字母大写
  17. $method = 'set' . ucfirst($name);
  18. //下面判断 this本作用域中, 有没有$method这个类成员方法,也就是setidnum和setAge这个方法
  19. if (method_exists($this, $method)) {
  20. //这里相当于访问的是本作用域中的idnum方法,传入的值也是idnum的值
  21. return $this->$method($name, $value); //传入name是拦截的属性的名,value是拦截的属性的值 这里return出去 其中这里类属性已经变为了set*,比如下面的setIdNum
  22. } else {
  23. return null;
  24. }
  25. }
  26. private function setAge($name, $value) //setIdNum这里相当于是未来私有方法的名称 $name是拦截的属性的名,value是拦截的属性的值
  27. {
  28. //设置信息
  29. $ad = '改变为私有属性';
  30. echo $ad;
  31. }
  32. private function setIdNum($name, $value) //setIdNum这里相当于是未来私有方法的名称
  33. {
  34. //设置信息 身份证号 做一些验证
  35. // property_exists检查类中是否存在该属性 类属性 不是方法,$idNum 私有属性,是有的
  36. if (property_exists($this, $name)) {
  37. // strlen检查值是不是18位
  38. return $this->$name = strlen($value) == 18 ? $value : null;
  39. }
  40. }
  41. private function getIdNum($name)
  42. {
  43. // 只返回后6位
  44. var_dump($name); //这里传入的是idNum也就是属性,其中下面this代表的是本类,也就是作用域.
  45. $flag = property_exists($this, $name) && !empty($this->$name); //empty判断是否为空
  46. var_dump($flag);
  47. if ($flag) {
  48. return '*********' . mb_substr($this->$name, -6, 6);
  49. } else {
  50. return '操作违规信息不合法';
  51. }
  52. }
  53. public function __get($name) //getIdNum 最终的值还是来到了魔术方法__get方法中
  54. {
  55. // return $this->$name;
  56. $method = 'get' . ucfirst($name);
  57. //下面判断 this本作用域中, 有没有$method这个类成员方法,也就是getIdNum这个方法
  58. if (method_exists($this, $method)) {
  59. //这里相当于访问的是本作用域中的idnum方法,传入的值也是idnum的值
  60. return $this->$method($name); //传入name是拦截的属性的名,value是拦截的属性的值 这里return出去的是getIdNum
  61. } else {
  62. return null;
  63. }
  64. }
  65. }
  66. $a = new Credit('胡歌', '341621199905015488');
  67. // echo $a->name
  68. $a->age = 20; //__set
  69. // echo $a->age; //__get
  70. $a->idNum = '341621199905015488';
  71. echo $a->idNum;//私有属性是通过__get魔术标签输出的

更多相关文章

  1. Android最佳实践之Notification、下拉刷新、内存及性能建议等
  2. 如何向android的framework里添加新类
  3. Android(安卓)application 和 activity 标签详解
  4. Android(安卓)- Rerofit-RxJava(转载)
  5. Activity属性设置大全
  6. Android(安卓)桌面组件widget
  7. Android事件分发-总结
  8. android监听Home键
  9. Android事件分发机制原理及源码分析

随机推荐

  1. android画图-解锁界面
  2. Android——TabWidget
  3. Android ViewHolder 优化 ListView
  4. Android倒计时器——CountDownTimer
  5. Android 如何加载大图片
  6. 在Android线程中设置控件的值会报错
  7. Android TabLayout导航条属性的设置
  8. Android开发遇到的问题
  9. Android 检测键盘是否显示及隐藏键盘
  10. Android 调用第三方浏览器打开