Blogger Information
Blog 35
fans 0
comment 0
visits 16928
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
0815-类扩展(继承),抽象和接口、全局成语和命名空间
三九三伏
Original
482 people have browsed it

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

属性重载

__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>';
Correcting teacher:PHPzPHPz

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