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 相关文章推荐
新浪新闻小偷
Oct 09 PHP
php 之 没有mysql支持时的替代方案
Oct 09 PHP
php5中类的学习
Mar 28 PHP
php array_search() 函数使用
Apr 13 PHP
php iconv() : Detected an illegal character in input string
Dec 05 PHP
Yii使用ajax验证显示错误messagebox的解决方法
Dec 03 PHP
ecshop 2.72如何修改后台访问地址
Mar 03 PHP
PHP的pcntl多进程用法实例
Mar 19 PHP
Yii框架实现记录日志到自定义文件的方法
May 23 PHP
PHP基于SPL实现的迭代器模式示例
Apr 22 PHP
php日志函数error_log用法实例分析
Sep 23 PHP
tp5.1 框架查询表达式用法详解
May 25 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
ThinkPHP关联模型操作实例分析
2012/09/23 PHP
PHP跨平台获取服务器IP地址自定义函数分享
2014/12/29 PHP
CodeIgniter扩展核心类实例详解
2016/01/20 PHP
总结PHP中数值计算的注意事项
2016/08/14 PHP
Ajax+Jpgraph实现的动态折线图功能示例
2019/02/11 PHP
二级域名转向类
2006/11/09 Javascript
JavaScript的Function详细
2006/11/14 Javascript
js 变量类型转换常用函数与代码[比较全]
2009/12/01 Javascript
JavaScript中的逻辑判断符&amp;&amp;、||与!介绍
2014/12/31 Javascript
深入理解JavaScript系列(41):设计模式之模板方法详解
2015/03/04 Javascript
JavaScript中常见的字符串操作函数及用法汇总
2015/05/04 Javascript
点击页面任何位置隐藏div的实现方法
2016/09/05 Javascript
ES6通过babel转码使用webpack使用import关键字
2016/12/13 Javascript
关于vue.js组件数据流的问题
2017/07/26 Javascript
浅谈React高阶组件
2018/03/28 Javascript
node.js环境搭建图文详解
2018/09/19 Javascript
Node.js中读取TXT文件内容fs.readFile()用法
2018/10/10 Javascript
JS函数本身的作用域实例分析
2020/03/16 Javascript
vue添加锚点,实现滚动页面时锚点添加相应的class操作
2020/08/10 Javascript
vue 实现把路由单独分离出来
2020/08/13 Javascript
[45:50]完美世界DOTA2联赛PWL S3 CPG vs Forest 第二场 12.16
2020/12/17 DOTA
Python进度条实时显示处理进度的示例代码
2018/01/30 Python
Flask框架踩坑之ajax跨域请求实现
2019/02/22 Python
Python实现的栈、队列、文件目录遍历操作示例
2019/05/06 Python
Python 实用技巧之利用Shell通配符做字符串匹配
2019/08/23 Python
python中的itertools的使用详解
2020/01/13 Python
Spring Boot中使用IntelliJ IDEA插件EasyCode一键生成代码详细方法
2020/03/20 Python
Linux安装Python3如何和系统自带的Python2并存
2020/07/23 Python
python PyAUtoGUI库实现自动化控制鼠标键盘
2020/09/09 Python
C/C++程序员常见面试题一
2012/12/08 面试题
介绍一下Java的事务处理
2012/12/07 面试题
励志演讲稿范文
2014/04/29 职场文书
货物运输服务质量承诺书
2014/05/29 职场文书
优秀教师自我评价范文
2014/09/27 职场文书
2015年公司工作总结
2015/04/25 职场文书
python 逐步回归算法
2021/04/06 Python