PHP面向对象程序设计中的self、static、parent关键字用法分析


Posted in PHP onAugust 14, 2019

本文实例讲述了PHP面向对象程序设计中的self、static、parent关键字用法.分享给大家供大家参考,具体如下:

看到php里面有关于后期静态绑定的内容,虽然没有完全看懂,但是也收获不少东西。

php官方手册介绍:
http://php.net/manual/zh/language.oop5.late-static-bindings.php

不存在继承的时候

不存在继承的意思就是,就书写一个单独的类来使用的时候。self和static在范围解析操作符 (::) 的使用上,并无区别。

  • 在静态函数中,self和static可以调用静态属性和静态函数(没有实例化类,因此不能调用非静态的属性和函数)。
  • 在非静态函数中,self和static可以调用静态属性和静态函数以及非静态函数

此时,self和static的表现是一样的,可以替换为该类名::的方式调用。

<?php
class Demo{
 public static $static;
 public $Nostatic; 
 public function __construct(){
  self::$static = "static";
  $this->Nostatic = "Nostatic";
 }
 public static function get(){
  return __CLASS__;
 }
 public function show(){
  return "this is function show with ".$this->Nostatic;
 }
 public function test(){
  echo Demo::$static."<br/>"; //使用类名调用静态属性
  echo Demo::get()."<br/>"; //使用类名调用静态属性
  echo Demo::show()."<br/>"; //使用类名调用静态属性
  echo self::$static."<br/>"; //self调用静态属性
  echo self::show()."<br/>"; //self调用非静态方法
  echo self::get()."<br/>"; //self调用静态方法
  echo static::$static."<br/>";//static调用静态属性
  echo static::show()."<br/>";//static调用非静态方法
  echo static::get()."<br/>"; //static调用静态方法
 }
}
$obj = new Demo();
$obj->test();

输出结果:

static
Demo
this is function show with Nostatic
static
this is function show with Nostatic
Demo
static
this is function show with Nostatic
Demo

继承的时候

在继承时,self和static在范围解析操作符 (::) 的使用上有差别。parent也是在继承的时候使用的。

<?php
class A{
 static function getClassName(){
  return "this is class A";
 }
 static function testSelf(){
  echo self::getClassName();
 }
 static function testStatic(){
  echo static::getClassName();
 }
}
class B extends A{
 static function getClassName(){
  return "this is class B";
 }
}
B::testSelf();
echo "<br/>";
B::testStatic();

输出结果:

this is class A
this is class B

self调用的静态方法或属性始终表示其在使用的时候的当前类(A)的方法或属性,可以替换为其类名,但是在类名很长或者有可能变化的情况下,使用self::的方式无疑是更好的选择。

static调用的静态方法或属性会在继承中被其子类重写覆盖,应该替换为对应的子类名(B)。

parent关键字用于调用父类的方法和属性。在静态方法中,可以调用父类的静态方法和属性;在非静态方法中,可以调用父类的方法和属性。

<?php
class A{
 public static $static;
 public $Nostatic; 
 public function __construct(){
  self::$static = "static";
  $this->Nostatic = "Nostatic";
 }
 public static function staticFun(){
  return self::$static;
 }
 public function noStaticFun(){
  return "this is function show with ".$this->Nostatic;
 }
}
class B extends A{
 static function testS(){
  echo parent::staticFun();
 }
 function testNoS(){
  echo parent::noStaticFun();
 }
}
$obj = new B();
$obj->testS();
echo "<br/>";
$obj->testNoS();

输出结果

static
this is function show with Nostatic

在文章的最后,我们分析一个手册上的例子

<?php
class A {
 public static function foo() {
  static::who();
 }
 public static function who() {
  echo __CLASS__."\n";
 }
}
class B extends A {
 public static function test() {
  A::foo();
  parent::foo();
  self::foo();
 }
 public static function who() {
  echo __CLASS__."\n";
 }
}
class C extends B {
 public static function who() {
  echo __CLASS__."\n";
 }
}
C::test();
?>

输出结果

A
C
C

我们单独拿出test方法进行分析:

public static function test() {
  A::foo();
  parent::foo();
  self::foo();
}

1)A::foo();这个语句是可以在任何地方执行的,它表示使用A去调用静态方法foo()得到'A'。

2)parent::foo();C的parent是B,B的parent是A,回溯找到了A的foo方法;static::who();语句中的static::调用的方法会被子类覆盖,所以优先调用C的who()方法,如果C的who方法不存在会调用B的who方法,如果B的who方法不存在会调用A的who方法。所以,输出结果是'C'。[注1]

3)self::foo();这个self::是在B中使用的,所以self::等价于B::,但是B没有实现foo方法,B又继承自A,所以我们实际上调用了A::foo()这个方法。foo方法使用了static::who()语句,导致我们又调用了C的who函数。[注2]

注1:补充解释上面的(2)

<?php
class A {
 public static function foo() {
  static::who();
 }
 public static function who() {
  echo __CLASS__."\n";
 }
}
class B extends A {
 public static function test() {
  A::foo();
  parent::foo();
  self::foo();
 }
 public static function who() {
  echo __CLASS__."\n";
 }
}
class C extends B {
 // public static function who() {
 //  echo __CLASS__."\n";
 // }
}
C::test();
?>

输出结果:

A B B

注2:补充解释上面的(3)

<?php
class A {
 public static function foo() {
  static::who();
 }
 public static function who() {
  echo __CLASS__."\n";
 }
}
class B extends A {
 public static function test() {
  A::foo();
  parent::foo();
  self::foo();
 }
 public static function foo() {
  echo "fooB"."\n";
 }
 public static function who() {
  echo __CLASS__."\n";
 }
}
class C extends B {
 public static function foo() {
  echo "fooC"."\n";
 }
 public static function who() {
  echo __CLASS__."\n";
 }
}
C::test();
?>

输出结果:

A C fooB

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
php 之 没有mysql支持时的替代方案
Oct 09 PHP
理解php Hash函数,增强密码安全
Feb 25 PHP
PHP设计模式之迭代器模式的深入解析
Jun 13 PHP
PHP函数preg_match_all正则表达式的基本使用详细解析
Aug 31 PHP
解决CodeIgniter伪静态失效
Jun 09 PHP
PHP SPL标准库之SplFixedArray使用实例
May 12 PHP
WordPress中转义HTML与过滤链接的相关PHP函数使用解析
Dec 22 PHP
php实用代码片段整理
Nov 12 PHP
PHP SFTP实现上传下载功能
Jul 26 PHP
thinkphp5框架实现的自定义扩展类操作示例
May 16 PHP
Laravel find in set排序实例
Oct 09 PHP
php设计模式之备忘模式分析【星际争霸游戏案例】
Mar 24 PHP
PHP命名空间定义与用法实例分析
Aug 14 #PHP
php中的依赖注入实例详解
Aug 14 #PHP
php基于 swoole 实现的异步处理任务功能示例
Aug 13 #PHP
thinkphp3.2框架中where条件查询用法总结
Aug 13 #PHP
thinkphp5框架结合mysql实现微信登录和自定义分享链接与图文功能示例
Aug 13 #PHP
php实现的表单验证类完整示例
Aug 13 #PHP
thinkphp3.2同时连接两个数据库的简单方法
Aug 13 #PHP
You might like
PHP_MySQL教程-第一天
2007/03/18 PHP
PHP的一个基础知识 表单提交
2011/07/04 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(二)
2014/06/23 PHP
PHP调用MySQL存储过程并返回值的方法
2014/12/26 PHP
通过chrome浏览器控制台(Console)进行PHP Debug的方法
2016/10/19 PHP
php微信公众号开发模式详解
2016/11/28 PHP
thinkPHP5.0框架自动加载机制分析
2017/03/18 PHP
PHP高精确度运算BC函数库实例详解
2017/08/15 PHP
详细解读php的命名空间(二)
2018/02/21 PHP
PHP设计模式之策略模式原理与用法实例分析
2019/04/04 PHP
javascript innerText和innerHtml应用
2010/01/28 Javascript
javascript Array数组对象的扩展函数代码
2010/05/22 Javascript
javascript中的document.open()方法使用介绍
2013/10/09 Javascript
js图片延迟技术一般的思路与示例
2014/03/20 Javascript
JavaScript中双叹号(!!)作用示例介绍
2014/04/10 Javascript
JavaScript中的Truthy和Falsy介绍
2015/01/01 Javascript
jQuery插件slicebox实现3D动画图片轮播切换特效
2015/04/12 Javascript
百度地图API之本地搜索与范围搜索
2015/07/30 Javascript
浅谈javascript中执行环境(作用域)与作用域链
2016/12/08 Javascript
使用rollup打包JS的方法步骤
2018/12/05 Javascript
详解vue-cli+es6引入es5写的js(两种方法)
2019/04/19 Javascript
使用JavaScript通过前端发送电子邮件
2020/05/22 Javascript
微信小程序拖拽排序列表的示例代码
2020/07/08 Javascript
在Echarts图中给坐标轴加一个标识线markLine
2020/07/20 Javascript
antd 表格列宽自适应方法以及错误处理操作
2020/10/27 Javascript
[01:33:30]DOTA2-DPC中国联赛 正赛 RNG vs Phoenix BO3 第二场 2月5日
2021/03/11 DOTA
python调用Delphi写的Dll代码示例
2017/12/05 Python
python获取酷狗音乐top500的下载地址 MP3格式
2018/04/17 Python
python读取Excel实例详解
2018/08/17 Python
Python3变量与基本数据类型用法实例分析
2020/02/14 Python
简单了解如何封装自己的Python包
2020/07/08 Python
HTML5 Canvas的常用线条属性值总结
2016/03/17 HTML / CSS
Java面向对象面试题
2016/12/26 面试题
护理专科毕业自荐信范文
2014/04/21 职场文书
企业文化宣传标语
2014/06/09 职场文书
企业管理不到位检讨书
2019/06/27 职场文书