Blogger Information
Blog 18
fans 0
comment 0
visits 10894
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
多态与魔术方法
手机用户1631860753
Original
558 people have browsed it

一.静态成员

  • 静态成员的优缺点:

优点:

1.存在多个实例,但是静态成员在内存中,只占一份
2.静态成员,执行效率比实例化高

缺点:

静态成员不能自动销毁,实例化就会自动销毁

  • 静态是多态的一种
  • 静态也是可以被继承的
  • 子类继承父类,访问父类的静态方法是用子类的 类名:: 进行访问

二.抽象类

  • 抽象类也是多态的一种
  • 抽象类用于描述一些事物所具有的的特性和行为,但是没有具体实现
  • 抽象类,有类也有方法,但是没有实例
  • 关键词:abstract 写在class前面
  • 抽象类可以继承抽象类
  • 继承了抽象类,那么就要把抽象类里面的所有方法都重写,不然会报错
  • 如果继承了抽象类,但是不能把所有方法都重写,那么只能把自己也变成抽象类
  • 抽象类里可以可以有普通的方法
  • 构造方法也可以在抽象类里使用
  • 抽象类:设计类与实现类是分离的,可以为子类提供一些,公用的方法,作为子类重写的模板来使用

  • 创建抽象类

  1. // 创建抽象类
  2. abstract class A
  3. {
  4. // 抽象方法
  5. abstract public function ff1();
  6. abstract public function ff2();
  7. }
  8. // new A(); // 抽象类不能实例化,不能生产出来对象,但是可以通过继承抽象类进行实例化
  9. // 抽象类继承抽象类,
  10. abstract class B extends A
  11. {
  12. // 构造方法在抽象类里使用
  13. protected $name1;
  14. protected $name2;
  15. public function __construct($name1, $name2)
  16. {
  17. $this->name1 = $name1;
  18. $this->name2 = $name2;
  19. }
  20. // 继承了抽象类,抽象类里的所有抽象方法也要重写,
  21. // 如果抽象类方法不全部都重写,那么只能自己也转变为抽象类
  22. // 抽象类里面也可以使用普通方法
  23. public function ff1()
  24. {
  25. return '我是: ' . $this->name1 . ',继承的抽象类A重写ff1';
  26. }
  27. }
  28. // 继承抽象类B 重写B没有重写的方法
  29. class C extends B
  30. {
  31. public function ff2()
  32. {
  33. return '我是: ' . $this->name2 . ',继承的抽象类B重写抽象类A中的ff2';
  34. }
  35. }
  36. $a = new C('ff1', 'ff2');
  37. echo $a->ff1();
  38. echo '<hr>';
  39. echo $a->ff2();
  • 输出

三.类常量

  • 类里面也有常量,被当成静态的成员
  • 有一些数据不能让别人更改的,就会用到常量
  • 不能用普通方法访问常量,要用静态方法访问 类名::
  • 类常量关键词:const

  • 常量

    1. class Cl
    2. {
    3. // const 常量关键词
    4. const CL_NAME = '常量';
    5. // 不能用普通方法访问,要用静态访问方法 类名::
    6. public function get_name()
    7. {
    8. return self::CL_NAME;
    9. }
    10. }
    11. echo Cl::CL_NAME;
    12. $obj = new Cl();
    13. echo $obj->get_name();

四.接口

  • 接口也是多态的一种,不管是普通类还是抽象类,都是单继承,就是一个子类只能继承一个父类
  • 那我们要一个类继承多个类,经过发展,接口实现了这个功能,它可以实现多个父类
  • 创建接口关键词: interface 是替换class
  • 接口只允许声明两个成员:1.常量,2.抽象方法
  • 接口不能继承,如果继承了就和单继承一样了
  • 使用接口关键词: implements 实现接口
  • 使用多个接口要用英文逗号隔开
  • 使用接口的时候,如果接口里有静态成员,重写的时候也要按照静态的方法写

  • 接口的运用

  1. // 创建抽象类
  2. abstract class A
  3. {
  4. // const 常量
  5. const APP_NAME = 'Mac';
  6. // 抽象方法
  7. abstract public function az($cj);
  8. }
  9. // 关键词 interface 创建接口
  10. interface Cja
  11. {
  12. public static function az_Cja($a);
  13. }
  14. interface Cjb
  15. {
  16. public function pj($b, $c);
  17. // 方法和函数一样,可以接收多个
  18. public function az_CJb($a);
  19. }
  20. // 用关键词 implements 来使用接口
  21. // 使用多个接口,用英文逗号隔开
  22. class B extends A implements Cja, Cjb
  23. {
  24. public function az($a)
  25. {
  26. return '安装成功: ' . $a;
  27. }
  28. // 使用接口,接口里有静态成员,那么重写的时候就要用静态的方法
  29. public static function az_Cja($a)
  30. {
  31. return '安装成功: ' . $a;
  32. }
  33. public function pj($b, $c)
  34. {
  35. return $b . '<hr>' . $c;
  36. }
  37. public function az_CJb($a)
  38. {
  39. return '安装成功: ' . $a;
  40. }
  41. }
  42. $obj = new B();
  43. echo $obj->pj('苹果台式电脑', '苹果笔记本');
  44. echo '<hr>';
  45. echo $obj->az('A安装包');
  46. echo '<hr>';
  47. echo B::az_Cja('B插件包'); // 静态成员用 类名:: 访问
  48. echo '<hr>';
  49. echo $obj->az_CJb('C插件包');

五.后期静态绑定

  • 后期静态绑定也叫延迟静态绑定,
  • 创建静态类属于前期, 静态::访问类就是后期
  • 后期静态绑定关键词:static 和静态成员关键词一样
  • 不管实例化谁,用了$this,它就会先找实例化的那个类里的方法
  • 静态继承的时候,是上下文环境,在调用过程中,没有正确识别调用者

  • 后期静态绑定的使用

  1. class A
  2. {
  3. public static function ff()
  4. {
  5. return '这是A类的ff';
  6. }
  7. public function show()
  8. {
  9. // return $this->ff(); // 静态成员不允许用 $this
  10. // return self::ff(); // 访问结果不匹配,要结果对应,实例化谁,就找谁拿结果
  11. return static::ff(); // 后期静态绑定,用 static关键词 替换 self关键词, 可以让实例化与结果匹配
  12. }
  13. }
  14. class B extends A
  15. {
  16. public static function ff()
  17. {
  18. return '这是B类的ff';
  19. }
  20. }
  21. $a = new A(); // 实例化 A
  22. echo $a->ff(); // 返回: 这是A类的ff
  23. echo '<hr>';
  24. $b = new B(); // 实例化 B
  25. echo $b->ff(); // 返回: 这是B类的ff

六.魔术方法

6.1 析构方法

  • __construct 构造方法,在new类的时候自动执行
  • __destruct 析构方法,在类注销(注销结束)的时候自动执行

  • 析构方法

  1. class A
  2. {
  3. public $name;
  4. public function __construct($name)
  5. {
  6. $this->name = $name;
  7. }
  8. // 析构方法是最后结束了执行
  9. public function __destruct()
  10. {
  11. echo '执行完了';
  12. }
  13. }
  14. $a = new A('析构方法');
  15. $name = $a->name;
  16. echo $a->name;
  17. echo '<hr>';
  18. unset($a); // 删除类,,相当于把类执行完了,结束这个类
  19. echo '<hr>';
  20. echo $name;

6.2 属性重载

  • __get 获取不可见和未定义的属性,触发这个魔术方法
  • __get 有一个参数,就相当于下标一样
  • 私有的和受保护的都可以使用
  • __set 修改成员的时候触发

  • 修改设置需要两个参数

    $key 相当于要修改的参数
    $value 相当于要修改的值

  • 通过返回 $this的key(参数名) = 要修改的值,进行修改

  • 不可见属性和未定义属性的获取与修改
  1. class A
  2. {
  3. protected $age;
  4. protected $jimi;
  5. private $name;
  6. public function __construct($name, $age, $jimi)
  7. {
  8. $this->name = $name;
  9. $this->age = $age;
  10. $this->jimi = $jimi;
  11. }
  12. // __get 有一个参数
  13. public function __get($n)
  14. {
  15. // 判断
  16. if ($n == 'name' || $n == 'age') {
  17. // return $name; // 这里的name和 类里的 $name 不是同一个
  18. // __get的参数: 我们要找的成员名字,我们在我们找name它就是name ,它就相当于是数组的下标一样
  19. // return $n;
  20. // $n 代表要找的成员名字
  21. return $this->$n;
  22. }
  23. // 判断它是否存在
  24. // empty 只要是没有值,也会当 true
  25. if (empty($this->$n)) {
  26. return '不存在';
  27. }
  28. return '抱歉,你暂时没有权限';
  29. }
  30. // 设置需要两个参数
  31. public function __set($key, $value)
  32. {
  33. // $key 相当于要修改的参数
  34. // $value 相当于要修改的值
  35. // 通过返回 $this的key(参数名) = 要修改的值,进行修改
  36. return $this->$key = $value;
  37. }
  38. }
  39. $a = new A('科学家', '25', '核心技术');
  40. echo $a->name . ',' . $a->age; // 科学家25
  41. echo '<hr>';
  42. echo $a->jimi; // 抱歉,你暂时没有权限
  43. echo '<hr>';
  44. $a->age = 30; // 修改参数
  45. echo $a->age; // 输出 30

6.3 方法重载

  • __call 访问未定义的方法时触发

  • __call 有两个参数

    第一个参数: 是访问的方法
    第二个参数: 是方法的传值

  • 示例

  1. class A
  2. {
  3. public function __call($key, $value)
  4. {
  5. return '方法名: ' . $key . '<br>方法参数: <pre>' . print_r($value, true) . '不存在';
  6. }
  7. }
  8. $a = new A();
  9. echo $a->adds(10, 30, 50);
  • 示例图

6.4 访问未定义的静态方法

  • __callStatic 访问未定义的静态方法时触发
  • 静态触发,就要使用静态方法
  • 没有静态方法访问,就会执行 __callStatic魔术方法

  • 示例

  1. class A
  2. {
  3. // 静态触发的话,就要使用静态方法
  4. public static function __callStatic($key, $value)
  5. {
  6. return '方法名: ' . $key . '<br>方法参数: <pre>' . print_r($value, true) . '不存在';
  7. }
  8. }
  9. // 没有这个静态方法,就会执行 __callStatic 魔术方法
  10. echo A::add(10, 30, 50);
  • 示例图

七.关键词与魔术方法

1.关键词:

关键词 解释
const 定义类常量
extends 扩展类,用一个类去扩展它的父类(继承类)
public 公开属性或者方法
protected 受保护的属性或者方法
private 私有属性或者方法
static 静态成员
abstract 抽象类或者方法
interface 创建接口
implements 实现接口
final 类不能被继承
parent:: 访问父类
$this 访问本类
self:: 访问本静态类
namespace 创建命名空间

2.魔术方法

方法 描述
__construct 构造方法,实例类的时候自动调用
__destruct 析构方法,类执行完后,自动调用
__call 在对象中调用一个不可访问方法时调用
__callStatic 用静态方式中调用一个不可访问方法时调用
__get 获取不可见和未定义的属性,自动调用
__set 修改成员的时候,自动调用
__isset 当对不可访问属性调用 isset()或 empty()时调用
__unset 当对不可访问属性调用unset()时被调用
__sleep 执行serialize()时,先调用这个函数
__wakeup 执行 unserialize()时,先会调用这个函数
__toString 类被当成字符串的回应方法
__invoke 调用函数的方式调用一个对象时的回应方法
__set_state 调用 var_export()导出类时,此静态方法会被调用
__clone 当对象复制完成时调用
__autoload 尝试加载未定义的类
__debugInfo 打印所需调试信息
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