博客列表 >0815-类扩展(继承),抽象和接口、全局成语和命名空间

0815-类扩展(继承),抽象和接口、全局成语和命名空间

三九三伏
三九三伏原创
2022年08月30日 19:42:11481浏览

一、类扩展(继承),抽象,接口

属性重载

__get(), __set()

  1. <?php
  2. namespace _0815;
  3. /////////////demo1//////////////
  4. /**
  5. * 属性重载 __get(),__set()
  6. *
  7. */
  8. //封装,重载,继承
  9. class User
  10. {
  11. //private:私有封装
  12. private array $data = [
  13. 'age' => 20,
  14. ];
  15. //查询接口
  16. public function __get($name)
  17. {
  18. $condition = array_key_exists($name, $this->data) ;
  19. return $condition ? $this->data[$name] : "$name 属性不存在";
  20. }
  21. //设置接口
  22. public function __set($name, $value)
  23. {
  24. $condition = array_key_exists($name, $this->data) ;
  25. if(!$condition){
  26. //这里如果不做提示和返回,对于把age错写成ag3,echo时又写对成age,是不是不好定位设置值不成功的问题?
  27. echo "$name 属性不存在<br>";
  28. // 但是这里出现了多处返回,是不是部分编辑器会报错?
  29. return ;
  30. }
  31. return $condition ? $this->data[$name] : "$name 属性不存在";
  32. }
  33. }
  34. $user =new User();
  35. echo $user->age.'<br>';
  36. $user->ag3 = 10;
  37. echo $user->age.'<br>';

遗留问题:
如上述代码注释所述,array_key_exist在__set中应用,多处return是否可以?不可以,如何处理注释中提到的问题?

方法重载

__call(), static function __callStatic()

  1. <?php
  2. namespace _0815;
  3. /////////////demo1//////////////
  4. /**
  5. * 属性重载 __get(),__set()
  6. * 方法重载 __call($name, $args), __callStatic($name, $args)
  7. */
  8. //封装,重载,继承
  9. class User
  10. {
  11. //private:私有封装
  12. private array $data = [
  13. 'age' => 20,
  14. ];
  15. //查询接口
  16. public function __get($name)
  17. {
  18. $condition = array_key_exists($name, $this->data) ;
  19. return $condition ? $this->data[$name] : "$name 属性不存在";
  20. }
  21. //设置接口
  22. public function __set($name, $value)
  23. {
  24. $condition = array_key_exists($name, $this->data) ;
  25. if(!$condition){
  26. //这里如果不做提示和返回,对于把age错写成ag3,echo时又写对成age,是不是不好定位设置值不成功的问题?
  27. echo "$name 属性不存在<br>";
  28. // 但是这里出现了多处返回,是不是部分编辑器会报错?
  29. return ;
  30. }
  31. return $condition ? $this->data[$name] : "$name 属性不存在";
  32. }
  33. // 可以自动拦截对方法的非法请求
  34. public function __call($name, $arguments)
  35. {
  36. printf('非法动态方法:%s,<pre>%s</pre>.<br>', $name, print_r($arguments, true));
  37. }
  38. // 拦截对静态方法的非法请求
  39. public static function __callStatic($name, $arguments)
  40. {
  41. printf('非法静态方法:%s,<pre>%s</pre>.<br>', $name, print_r($arguments, true));
  42. }
  43. }
  44. $user =new User();
  45. echo $user->age.'<br>';
  46. $user->ag3 = 10;
  47. echo $user->age.'<br>';
  48. // 非静态方法
  49. $user->hello('路人甲','4352259');
  50. // 静态方法
  51. User::world('路人乙','28375985');

THINKPHP查询构造器模拟

  1. //ThinkPHP,查询构造器,数据库操作
  2. class Query
  3. {
  4. public function table()
  5. {
  6. echo 'Query table()->';
  7. return $this;
  8. }
  9. public function where()
  10. {
  11. echo 'Query where()->';
  12. return $this;
  13. }
  14. public function find()
  15. {
  16. echo 'Query find()<br>';
  17. }
  18. }
  19. // 查询入口
  20. class Db
  21. {
  22. //实例化时自动连接数据库
  23. // public function __construct()
  24. // {
  25. // self::connect();
  26. // }
  27. public static function __callStatic($name, $arguments)
  28. {
  29. // printf('方法:%s,参数:<pre>%s</pre>',$name, print_r($arguments, true));
  30. // 所有查询在此完成,单入口查询
  31. return call_user_func_array([new Query, $name] , $arguments);
  32. }
  33. }
  34. Db::table('think_user')->where('id', 1)->find();

类扩展(继承)

  1. /**
  2. * 类的扩展(继承)/抽象/最终
  3. * 1. 可继承成员protected
  4. * 2. extends: 类成员的来源
  5. * 3. parent:父类引用
  6. */
  7. class Person
  8. {
  9. //属性
  10. // public:公共成员,类内、子类、类外部可访问
  11. public string $email = 'admin@php.cn';
  12. // private:私有成员,类内可访问。
  13. private int $id = 10;
  14. //protected:受保护成员,类内、子类可访问。
  15. protected string $name;
  16. //方法
  17. public function __construct($name)
  18. {
  19. $this->name =$name;
  20. }
  21. // 自定义方法
  22. protected function getInfo():string
  23. {
  24. return $this->name;
  25. }
  26. }
  27. class Stu extends Person
  28. {
  29. //只需要扩展属性和方法
  30. // 属性扩展
  31. private string $lesson;
  32. private int $score;
  33. //方法扩展
  34. // 构造方法扩展
  35. public function __construct($name, $lesson, $score)
  36. {
  37. //引用父类
  38. parent::__construct($name);
  39. $this->lesson = $lesson;
  40. $this->score =$score;
  41. }
  42. // 为方便外部访问,由public定义
  43. public function getInfo(): string
  44. {
  45. return parent::getInfo().'同学,'.$this->lesson.'成绩:'.$this->score.'<br>';
  46. }
  47. }
  48. $stu = new Stu('路人甲', 'php', 99);
  49. echo $stu->getInfo();

抽象类

  1. // 禁用父类,仅允许通过他的子类来访问父类成员。
  2. // 把当前类声明为抽象类abstract。
  3. // 如果类中有抽象方法,则必须声明为抽象类。
  4. abstract class demo1
  5. {
  6. public string $name = 'admin';
  7. // 抽象方法,没有具体实现体的方法应该声明成抽象方法。
  8. abstract public static function getInfo($name);
  9. }
  10. class demo2 extends demo1
  11. {
  12. // 在子类中必须实现父类抽象方法,否则报错。
  13. public static function getInfo($name)
  14. {
  15. return 'Hello,'.$name;
  16. }
  17. }
  18. echo demo2::getInfo('路人甲');

最终类

  1. // final最终类,禁止继承,直接用
  2. final class demofin
  3. {
  4. }
  5. //继承会报错
  6. class demo extends demofin
  7. {
  8. }

接口

  1. //接口:升级版的抽象类
  2. interface iUser
  3. {
  4. //接口的属性必须是常量
  5. public const NATION = 'CHINA';
  6. //接口方法必须是public
  7. public function m1();
  8. public function m2();
  9. }
  10. // 工作类:实现接口内容
  11. class demo1 implements iUser
  12. {
  13. // 接口中的抽象方法必须在工作类中全部实现
  14. public function m1()
  15. {
  16. }
  17. public function m2()
  18. {
  19. }
  20. }
  21. // 仅实现一部分,需声明为抽象子类
  22. abstract class Demo2 implements iUser
  23. {
  24. public function m1()
  25. {
  26. }
  27. }
  28. class demo3 extends Demo2
  29. {
  30. public function m2()
  31. {
  32. }
  33. }
  34. // php是单继承,可以通过接口间接多继承,不推荐
  35. interface A
  36. {
  37. }
  38. interface B
  39. {
  40. }
  41. interface C
  42. {
  43. }
  44. // 多继承
  45. class Test implements A, B, C
  46. {
  47. }
  48. interface iDb
  49. {
  50. // 插入
  51. public static function insert(array $data);
  52. // 更新
  53. public static function update(array $data, string $where);
  54. // 删除
  55. public static function delete(string $where);
  56. // 查询
  57. public static function select(array $options);
  58. }
  59. //这个地方上课时没有implements,是默认的么?
  60. abstract class aDb implements iDb
  61. {
  62. // 插入
  63. public static function insert(array $data)
  64. {
  65. }
  66. // 更新
  67. public static function update(array $data, string $where)
  68. {
  69. }
  70. // 删除
  71. public static function delete(string $where)
  72. {
  73. }
  74. // 查询
  75. public static function select(array $options)
  76. {
  77. }
  78. }
  79. class Db extends aDb
  80. {
  81. }

二、全局成员和命名空间

全局成员

全局成员:函数,常量,类/接口,全局有效,禁止重复声明

命名空间

作用

解决全局成员命名冲突问题

声明

  1. namespace _0815;
  2. function hello()
  3. {
  4. }
  5. const A = 1;
  6. class D
  7. {
  8. }
  9. namespace _0815_1;
  10. function hello()
  11. {
  12. }
  13. const A = 1;
  14. class D
  15. {
  16. }

跨空间访问

  1. namespace one;
  2. class Demo1
  3. {
  4. public static string $name = 'admin';
  5. }
  6. // 当存在命名空间时,全局成员应该使用完整名称。
  7. // 完整类名 = 空间名称\类名
  8. // ::class 获取完整类名
  9. echo Demo1::class.'<br>';
  10. namespace two;
  11. class demo1
  12. {
  13. public static string $name = '路人甲';
  14. }
  15. echo Demo1::class.'<br>';
  16. // 跨空间访问
  17. // echo one\Demo1::$name;->实际访问’two\one\Demo1‘
  18. // 要从根空间'\'开始
  19. echo \one\Demo1::$name;

命名空间的类型

  1. // 1. 当前路径:非限定名称 Index
  2. // 2. 相对路径:限定名称 two\Index
  3. // 3. 绝对路径:完全限定名称 \one\two\Index
  4. namespace _0815;
  5. namespace one;
  6. class index
  7. {
  8. public static function show()
  9. {
  10. return __METHOD__;
  11. }
  12. }
  13. echo Index::show().'<br>';
  14. echo two\Index::show().'<br>';
  15. // 空间可分层
  16. namespace one\two;
  17. class index
  18. {
  19. public static function show()
  20. {
  21. return __METHOD__;
  22. }
  23. }
  24. echo Index::show().'<br>';

命名冲突

use起别名简化长度

  1. namespace one;
  2. class Index
  3. {
  4. public static function show()
  5. {
  6. return __METHOD__;
  7. }
  8. }
  9. echo \one\two\three\Index::show().'<br>';
  10. // use默认使用完全限定名称的类名/绝对路径,用别名简化长度。
  11. use \one\two\three\Index as UserIndex;
  12. echo UserIndex::show().'<br>';
  13. //-----------------------------------------
  14. namespace one\two\three;
  15. class Index
  16. {
  17. public static function show()
  18. {
  19. return __METHOD__;
  20. }
  21. }


上面代码中,如果namespace one没有Index类,那么use可以直接起别名Index,

  1. ...
  2. use \one\two\three\Index as Index;
  3. echo Index::show().'<br>';

当前类别名Index与原始类名相同,还可以不写

  1. ...
  2. use \one\two\three\Index;
  3. echo Index::show().'<br>';
声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议