abstract:一.类的继承 + 类的继承,是为了代码复用 + PHP只支持单继承 + 继承必须发生在二个或二个以上的类之间 + 父类也叫超类,基类,子类也叫派生类 之前我们是用函数来实
一.类的继承
+ 类的继承,是为了代码复用
+ PHP只支持单继承
+ 继承必须发生在二个或二个以上的类之间
+ 父类也叫超类,基类,子类也叫派生类
之前我们是用函数来实现代码复用,现在我们用类的继承来实现代码复用
类继承使用 extends关键字
* 继承环境下:
* protected,public 可以在子类中访问
* 访问限制符是受到类作用域限制的
* 类常量,不受限制的.可以在子类中直接使用
class ParentClass { public $name; protected $course; private $salary; const SITE_NAME = 'PHP中文网'; //构造方法 public function __construct($name,$course,$salary) { $this->name = $name; $this->course = $course; $this->salary = $salary; } //访问本类私有成员 public function getSalary() { return $this->salary; } public function getCourse() { //受保护的成员,可以在子类中访问 return $this->course; } } //创建子类,继承自parentClass 类 class ChildClass extends ParentClass { //子类中允许重写父类中的同名方法,也叫多态 public function getCourse() { //受保护的成员,可以在子类中访问 // return $this->course; return $this->name.'的成名地点是'.parent::getCourse(); } public function getSalary() { // return $this->salary; } } $child = new ChildClass('张辽','白门楼',8000); echo $child->name.'<br>'; //echo $child->course.'<br>';//访问失败 父类受保护的属性 echo $child->getCourse().'<br>'; //echo $child->getSalary(); //失败 不可以访问父类中私有属性 echo ChildClass::SITE_NAME.'<br>';
二.范围解析符的使用
* 使用场景:
+ 访问类中的静态成员
+ 访问类中的常量
* 使用主体:
+ 在类中使用关键字:self static parent
+ 在类外可直接使用类名:className
class Book { //声明一个普通的动态成员属性 public $name = "mysql从删库到跑路"; //声明静态成员的属性 protected static $author = '朱老师'; //类常量,不要设置访问限制,本身就属于类的 const PRICE = 99; //动态方法,既可以访问动态成员,也可以访问静态成员 public function getInfo1() { //普通动态成员 // return $this->name; //静态成员 //尽管可以在普通方法中访问静态成员,但是推荐尽可能不用这样做 // return self::$author; //self::$成员名 return self::PRICE; } //静态方法,属于类的必须要用类来调用,可以被所有该类的对象所共享 public static function getInfo2() { //普通动态成员,不能访问 // return $this->name; //静态成员 // return self::$author; //self::$成员名 return self::PRICE; } } //子类Study 继承自Book类 class Study extends Book { public static function getInfo3() { //访问父类的静态成员 // return Book::$author; //应该使用当前父类的引用标识:parent // return parent::$author; return static::$author; } } $book = new Book(); //echo $book->name; echo $book->getInfo1(); //echo Book::getInfo2(); $study = new Study(); echo $study->getInfo3();
三.static关键字
用处如下:
+ 定义与访问类中的静态成员;
+ 访问类常量
+ 后期静态绑定(延迟静态绑定)
class MyClass { //const 定义类常量 const DOMAIN = 'm.sbmmt.com'; //static 定义静态属性:被类的所有实例所共享 public static $desc = '免费公益,海量资源'; //静态方法 public static function getDesc() { //类常量 // $domain = self::DOMAIN; $domain = static::DOMAIN; //静态属性 // $desc = self::$desc; $desc = static::$desc; return '('.$domain.')'.$desc; } } //外部访问类中的静态属性 echo MyClass::$desc.'<br>'; echo MyClass::getDesc();
四.后期静态绑定 (static)
+ 使用在静态继承的上下文环境中;
+ 动态匹配静态成员的调用者,而不是声明者;(谁调用我,我就是谁)
+ 静态方法与调用者的绑定在运行阶段才可以确定
//定义一个父类 class Father { //静态属性 public static $money = 50000; //静态方法 public static function getClass() { //返回当前类名 return __CLASS__; } //静态方法 public static function getMoney() { // return self::getClass().'=>'.self::$money; //如果这样定义子类继承之后调用返回的是父类的self //static用在静态继承的上下文中,调用者是动态的,动态设置静态成员的调用者(调用主体) return static::getClass().'=>'.static::$money; } } //定义子类,继承自Father class Son extends Father { //覆写父类的静态属性 public static $money = 30000; //覆写父类的静态方法 public static function getClass() { //返回当前类名 return __CLASS__; } } //调用Father中的静态方法,来获取一下类名 echo Father::getClass().'<br>'; echo Father::getMoney().'<br>'; //调用子类Son类中的静态成员 echo Son::$money.'<br>'; echo Son::getClass().'<br>'; echo '<hr>'; //子类中调用父类中的getMoney() echo Son::getMoney(),'<br>'; //希望返回Son::30000 而现在返回的是父类的值 改成static就变成希望的返回值了
五.重载技术
+ 重载: 动态创建类属性和方法;
+ 属性重载:
* __set($name,$value)
* __get($name)
* __isset($name)
* __unset($name)
+ 方法重载: (当用户调用一个不存在的普通方法时触发__call 当用户调用一个没有访问权限或着不存在的静态方法自动调用__callstatic)
* __call($method,array $args)
* __callStatic($method,array $args)
重载的实现手段:通过魔术方法
1.属性重载
__set(), __get() __isset() , __unset() 当设置,调用,判断是否存在,销毁 类中不存在的属性,或者不可访问的属性时 ,会调用属性重载
class Visit { protected $data = []; //声明一个空数组 public function __isset($name) //$name属性不存在或者受保护的时候调用 { return isset($this->data[$name]); //因为这个$name属性不存在 返回false } public function __get($name) //当调用的$name 属性不存在或者受保护的时候, 设置$data的一个值 { return $this->data[$name]; } public function __set($name,$value) //当设置$name 的值 不存在或者受保护的时候, 设置$data的一个元素为这个不存在的值 { $this->data[$name] = $value; } public function __unset($name) //当销毁一个不存在的值或者受保护的属性 提示不让他销毁 { echo '禁止销毁'; } } $visit = new Visit(); if(isset($visit->table)){ //判断是否存在 echo $visit->table,'<br>'; //存在就输出它 }else{ $visit->table = 'table_staff'; //更新操作 不存在就设置他 } //因为上边他不存在,所以走的else __set我设置方法让他给$data['table']设置了值'table_staff' 当我调用不存在的table属性, __get 我设置的让他返回$data['table']的值 ,所以返回成功了 echo $visit->table,'<br>'; //table_staff unset($visit->table); //禁止销毁
2,方法重载 __call(),__callStatic()
当访问一个不存在的一个动态普通方法的时候会自动调用__call()
当访问一个不存在的一个静态方法的时候会自动调用__callStatic()
方法重载更多用在跨类的方法调用上
require 'public/Site.php'; class Web { //当访问一个不存在的一个动态普通方法的时候会自动调用 public function __call($name, $arguments) { // return '方法是:'.$name.'<br>'.'参数列表:'.var_export($arguments,true); //方法重载更多用在跨类的调用上 return call_user_func_array([(new Site),'show'],$arguments); //返回回到函数处理的结果 将$arguments(array)当做参数传到实例化对象Site的show方法中 } //当访问一个不存在的一个静态方法的时候会自动调用 public static function __callStatic($name, $arguments) { // return '方法是:'.$name.'<br>'.'参数列表:'.var_export($arguments,true); //方法重载更多用在跨类的调用上 return call_user_func_array(['Site','add'],$arguments); //将argunments当做参数传入到Site类中的静态方法add中 } } $web = new Web(); //访问一个不存在的方法 echo $web->show('php中文网','海量资源,公益免费').'<hr>'; //访问一个不存在的静态方法 echo Web::add(30,50);
Correcting teacher:韦小宝Correction time:2018-11-26 11:12:55
Teacher's summary:嗯!不错!写的很棒!不要骄傲!继续加油吧