Blogger Information
Blog 26
fans 0
comment 0
visits 21909
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
面向接口编程:接口与trait
溪边小树
Original
838 people have browsed it

本次课程中细致讲解了关于接口与trait的基本语法与使用场景,老师希望大家能深刻理解课堂中讲解的相关内容。
接口继承是重点所在,trait的基本功能是代码复用,请分别用实例展示。

接口继承实例:

  1. <?php
  2. // 接口的使用场景2:多接口继承,一个接口同时继承多个接口
  3. // 接口可以突破php类的继承限制, 允许多继承, 形成了多层级的接口
  4. interface iStudent
  5. {
  6. // 接口常量
  7. const COLLEDGE = 'XX大学';
  8. }
  9. interface iStudent1 extends iStudent
  10. {
  11. // 接口常量
  12. const MAJOR = '网络编程';
  13. }
  14. // 接口实现多继承
  15. interface iStudent2 extends iStudent, iStudent1
  16. {
  17. // 接口方法
  18. public function message();
  19. }
  20. // 实现类
  21. class Student implements iStudent, iStudent1,iStudent2
  22. {
  23. // 必须实现接口中的抽象方法
  24. public function message()
  25. {
  26. return iStudent1::MAJOR . ' 是 ' .iStudent::COLLEDGE.'重点专业之一!' ;
  27. }
  28. }
  29. echo ( new Student)->message();
  30. echo '<hr>';
  31. // 实现类1
  32. class Student1 implements iStudent2
  33. {
  34. // 必须实现接口中的抽象方法
  35. public function message()
  36. {
  37. return iStudent1::MAJOR . ' 目前是 ' .iStudent::COLLEDGE.'重点专业之一!' ;
  38. }
  39. }
  40. echo ( new Student1)->message();
  41. // 接口场景3: 用抽象类来部分实现一个接口
  42. interface iDbBase
  43. {
  44. // 接口方法
  45. // 这里全部采用静态方法, 可省去实例化操作
  46. // 数据库常用的CURD(增删改查)操作
  47. public static function insert($db, $data);
  48. public static function select($db, $options=[]);
  49. public static function update($db,$options);
  50. public static function delete($db, $where);
  51. // 连接数据库
  52. public static function connect($dsn, $username, $password);
  53. }
  54. // 用一个抽象类只实现接口的连接方法: connect()
  55. abstract class aDb implements iDbBase
  56. {
  57. protected static $db = null;
  58. public static function connect($dsn, $username, $password)
  59. {
  60. if (is_null(self::$db)) {
  61. try {
  62. // 连接数据库, 创建pdo对象
  63. self::$db = new \PDO($dsn, $username, $password);
  64. } catch (PDOException $e) {
  65. die($e->getMessage());
  66. }
  67. }
  68. return self::$db;
  69. }
  70. }
  71. // 工作类: 通用查询
  72. class DB1 extends aDb
  73. {
  74. public static function insert($db, $data)
  75. {
  76. // ...
  77. }
  78. public static function select($db, $options=[])
  79. {
  80. $sql = 'SELECT `id`,`name`,`email` FROM `users` LIMIT 5';
  81. return$db->query($sql)->fetchAll(\PDO::FETCH_ASSOC);
  82. }
  83. public static function update($db,$options)
  84. {
  85. }
  86. public static function delete($db, $where)
  87. {
  88. // ...
  89. }
  90. }
  91. // 客户端
  92. $config = [
  93. 'type' => $type ?? 'mysql',
  94. 'host' => $hsot ?? 'localhost',
  95. 'dbname' => $dbname ?? 'phpedu',
  96. 'charset' => $charset ?? 'utf8',
  97. 'port' => $port ?? '3306',
  98. 'username' => $username ?? 'root',
  99. 'password' => $password ?? '123456',
  100. ];
  101. // 创建PDO数据源
  102. $dsn = sprintf('%s:host=%s;dbname=%s;',$config['type'],$config['host'],$config['dbname']);
  103. // 使用自定义用户密码
  104. $username = $config['username'];
  105. $password = 'root';
  106. // 连接数据库: 实际上调用的是抽象类中的connect()方法完成,返回连接对象$db
  107. $db = DB1::connect($dsn, $username, $password);
  108. // 查询操作
  109. $users = DB1::select($db);
  110. // 遍历结果集
  111. foreach ($users as list('id'=>$id, 'name'=>$name,'email'=>$email)) {
  112. printf('%s => %s : %s <br>', $id, $name, $email);
  113. }
  114. echo '<hr>';
  115. // 接口使用场景4: 接口是实现多态的重要手段
  116. // 1. 数据库操作接口
  117. interface iDb
  118. {
  119. // 构造方法: 用于连接数据库
  120. public function __construct(...$params);
  121. // 1. 新增
  122. public function insert(array $data);
  123. // 2. 查询
  124. public function select(array $options = []);
  125. // 3. 更新
  126. public function update(array $options);
  127. // 4. 删除
  128. public function delete(array $where);
  129. }
  130. /////////////////////////////////////////////////////////
  131. // 2. 使用PDO方式实现iDB接口, 仅以查询select()演示
  132. class DB_PDO implements iDb
  133. {
  134. protected $db = null;
  135. public function __construct(...$params)
  136. {
  137. list($dsn, $username, $password) = $params;
  138. $this->db = new PDO($dsn, $username, $password);
  139. }
  140. // 1. 新增
  141. public function insert(array $data)
  142. {
  143. // ...
  144. }
  145. // 2. 查询
  146. public function select(array $options = [])
  147. {
  148. echo '<h3>PDO:</h3>';
  149. $sql = 'SELECT `id`,`name`,`email` FROM `users` LIMIT 3';
  150. return $this->db->query($sql)->fetchAll(PDO::FETCH_ASSOC);
  151. }
  152. // 3. 更新
  153. public function update(array $options)
  154. {
  155. // ...
  156. }
  157. // 4. 删除
  158. public function delete(array $where)
  159. {
  160. // ...
  161. }
  162. }
  163. /////////////////////////////////////////////////////////
  164. // 3. 使用MySQLi方式实现iDB接口,仅以查询select()演示
  165. class DB_MySQLi implements iDb
  166. {
  167. protected $db = null;
  168. public function __construct(...$params)
  169. {
  170. list($host, $username, $password, $dbname, $charset) = $params;
  171. $this->db = new MySQLi($host, $username, $password, $dbname);
  172. $this->db->set_charset($charset);
  173. }
  174. // 1. 新增
  175. public function insert(array $data)
  176. {
  177. // ...
  178. }
  179. // 2. 查询
  180. public function select(array $options = [])
  181. {
  182. echo '<h3>MySQLi:</h3>';
  183. $sql = 'SELECT `id`,`name`,`email` FROM `users` LIMIT 3';
  184. return $this->db->query($sql)->fetch_all(MYSQLI_ASSOC);
  185. }
  186. // 3. 更新
  187. public function update(array $options)
  188. {
  189. // ...
  190. }
  191. // 4. 删除
  192. public function delete(array $where)
  193. {
  194. // ...
  195. }
  196. }
  197. /////////////////////////////////////////////////////////
  198. // 4. 创建数据库通用操作类,用来统一客户端调用方式(静态实现)
  199. class DB
  200. {
  201. // 新增
  202. public static function insert(iDb $db, array $data)
  203. {
  204. return $db->insert($data);
  205. }
  206. // 查询
  207. public static function select(iDb $db, array $options = [])
  208. {
  209. return $db->select($options = []);
  210. }
  211. // 更新
  212. public static function update(iDb $db, array $options)
  213. {
  214. return $db->update($options);
  215. }
  216. // 删除
  217. public static function delete(iDb $db, array $where)
  218. {
  219. return $db->delete($where);
  220. }
  221. }
  222. /////////////////////////////////////////////////////////
  223. // 客户端代码
  224. $config = [
  225. 'type' => $type ?? 'mysql',
  226. 'host' => $host ?? 'localhost',
  227. 'dbname' => $dbname ?? 'phpedu',
  228. 'charset' => $charset ?? 'utf8',
  229. 'port' => $port ?? '3306',
  230. 'username' => $username ?? 'root',
  231. 'password' => $password ?? 'root',
  232. ];
  233. extract($config);
  234. // 1. PDO实现
  235. $dsn = sprintf('%s:host=%s;dbname=%s;', $type, $host, $dbname);
  236. // 使用自定义密码
  237. $password = 'root';
  238. $db = new DB_PDO($dsn, $username, $password);
  239. $db = new DB_MySQLi($host, $username, $password, $dbname, $charset);
  240. var_dump($db);
  241. // SQL执行操作,以查询为例,无论数据库是什么类型,都无须改动查询代码
  242. // 因为是面向接口编程, DB_PDO, DB_MySQLi都实现了同一接口
  243. // 只要将对象参数的类型限定在接口上就可以实现多态
  244. // 此时, $db 即可是DB_PDO类实例, 也可以是DB_MySQLi类实例, 就看你的心情了
  245. $users = DB::select($db);
  246. // 遍历结果集
  247. foreach ($users as list('id' => $id, 'name' => $name, 'email' => $email)) {
  248. printf('%s => %s : %s <br>', $id, $name, $email);
  249. }

trait实例:

  1. <?php
  2. // trait 功能与语法
  3. // trait: php5.4+, 代码复用
  4. // trait:与抽象类,接口一样不能实例化, 只能嵌入到宿主类中使用
  5. // triat是一个特殊类: 1. 常规, 2. 静态, 3. 抽象, 不能用类常量
  6. trait tDemo
  7. {
  8. // 常规
  9. protected $name = '张嘎子';
  10. public function getName()
  11. {
  12. return $this->name;
  13. }
  14. // 静态
  15. public static $sex = '男';
  16. public static function getSex()
  17. {
  18. return self::$sex;
  19. }
  20. // 抽象
  21. // 抽象静态属性
  22. public static $age;
  23. // 抽象静态方法
  24. abstract public static function getAge();
  25. }
  26. // 客户端
  27. class User
  28. {
  29. // 类中使用trait , 用use 关键
  30. use tDemo;
  31. // 将use tDemo 理解为加载
  32. // require tDemo;
  33. // 常规
  34. // protected $name = '张嘎子';
  35. // public function getName()
  36. // {
  37. // return $this->name;
  38. // }
  39. // // 静态
  40. // public static $sex = '男';
  41. // public static function getSex()
  42. // {
  43. // return self::$sex;
  44. // }
  45. // // 抽象
  46. // // 抽象静态属性
  47. // public static $age;
  48. public static function getAge()
  49. {
  50. return self::$age;
  51. }
  52. }
  53. $user = new User;
  54. User::$age = 16;
  55. echo $user->getName() . ' : ' . User::getSex() . ' ===> ' . User::getAge();
  56. echo '<hr>';
  57. // trait 功能1: 代码复用
  58. trait tDemo1
  59. {
  60. // 格式化打印
  61. public function write()
  62. {
  63. $props =get_class_vars(__CLASS__);
  64. printf('<pre>%s</pre>', print_r($props, true));
  65. }
  66. }
  67. // User1
  68. class User1
  69. {
  70. use tDemo1;
  71. protected $course = '网络编程';
  72. protected $score = 80;
  73. protected $mainpoint = ['类', '接口', 'trait'];
  74. }
  75. (new User1)->write();
  76. // User2
  77. class User2
  78. {
  79. use tDemo1;
  80. protected $course = '网站设计原理';
  81. protected $score = 90;
  82. protected $mainpoint = ['前端', '框架', '数据库'];
  83. }
  84. (new User2)->write();
  85. echo '<hr>';
  86. // trait2: 在继承上下文环境中, 具有优先级, 通过优先的设置, 降低单继承的影响
  87. trait tDemo2
  88. {
  89. public static $name = 'Trait中的属性';
  90. public static function hello()
  91. {
  92. return 'Trait中的方法: ' . __METHOD__;
  93. }
  94. }
  95. // 基类/父类
  96. class Dad
  97. {
  98. // public static $name = '基类中的属性';
  99. public static function hello()
  100. {
  101. return '基类中的方法: ' . __METHOD__;
  102. }
  103. }
  104. // 扩展类/子类
  105. class Son extends Dad
  106. {
  107. use tDemo2;
  108. // trait中的同名方法将父类中同名方法覆盖了, 重写了
  109. // public static $name = '扩展类中的属性';
  110. public static function hello()
  111. {
  112. return '扩展类中的方法: ' . __METHOD__;
  113. }
  114. // 当前类的同名方法又会覆盖掉trait中同名方法
  115. }
  116. // 客户端
  117. echo Son::hello();
  118. // 方法使用的优先级:子类 > trait > 父类

课程学习小结

本次课程老师从浅显易懂的实例出发,细致讲解了接口继承及trait使用的相关内容,通过回看视频及讲义代码,加深了理解,尤其是接口继承及多态的使用场景、trait在宿主类中的使用方法及与父类、子类间调用相应方法的优先级比较等,相关代码基本模仿老师的实例格式进行修改实现,虽然花费了不少时间,但对促使自己多动手实践的习惯养成又进了一步,调试成功后还是感觉挺好的。!

Correcting teacher:天蓬老师天蓬老师

Correction status:qualified

Teacher's comments:初学编程, 就像是小孩子学说话, 都是从模仿开始的, 在模仿中慢慢就会掌握规律, 最后形成自己的知识了
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post