今天在群里发现有人说,PHP可以用::调用非静态方法,一致没这么试过,发现了鸟哥的blog写了这个问题的具体解释,就搬过来:

这个问题乍看, 确实很容易让人迷惑, 但实际上, 造成这样的误解的根本原因在于: 在PHP中, 判断静态与否不是靠”::”(PAAMAYIM_NEKUDOTAYIM)符号, 而是靠calling scope.

那么, 什么是calling scope?

在PHP中, 调用一个方法的时候, $this指针指向的对象就是这个方法被调用时刻的calling scope. 对于下面的例子:

<?php
Foo::bar();
?>

在调用bar方法的时候, 处于一个没有calling scope域的上下文中, 所以这个是静态调用.

而对于如下的例子:

<?php
class A {
public function test() {
Foo::bar();
}
}
$a = new A();
$a->test();

在调用bar方法的时候, 处于一个$a对象的上下文中, 也就是说, 此时的calling scope是$a对象, 所以这个其实不是静态调用.

为了验证这一个结论, 请看下面的一个实际例子:

<?php
class Foo {
public function bar() {
var_dump($this);
}
}
class A {
public function test() {
Foo::bar();
}
}
$a = new A();
$a->test();
?>

输出什么呢?

object(A)#1 (0) {
}

在调用bar的时候, 这个看似”静态”调用的调用, $this指针却是被赋值的, 指向的是$a对象, 那么这个还算静态调用么?

我举这个例子是为了说明这个问题, 但大家在实际的应用中, 大家尽量要避免使用”::”来调用一个非静态的方法, PHP也会对于这种调用给出一个Strict 警告:

也许有人会说这个应该算bug吧? 其实不然, 更多的应该是错误使用造成的, 因为你在一个有calling scope的上下文中采用”静态的形式”调用了一个类的非静态方法所致.

那么PHP为什么要这么设计呢? 考虑下面的例子:

<?php
class A {
public function __construct() {
}
}
class B extends A {
public function __construct() {
parent::__construct();
}
}

当我们调用父类的构造函数的时候, 我们是有意的要把当前的scope传递给父类的构造函数作为calling scope的.

PHP的Calling Scope(::调用非静态方法)的更多相关文章

  1. PHP中静态(static)调用非静态方法详解

    1.PHP中可以静态调用非静态方法么? 今天我被问到PHP中可不可以使用 className::methodName() 的方法来调用一个没有声明static的方法.在我的印象中,我好像是见过这种用法 ...

  2. java中静态方法中为什么不能使用this、super和直接调用非静态方法

    这个要从java的内存机制去分析,首先当你New 一个对象的时候,并不是先在堆中为对象开辟内存空间,而是先将类中的静态方法(带有static修饰的静态函数)的代码加载到一个叫做方法区的地方,然后再在堆 ...

  3. php静态调用非静态方法

    <?php /** * php静态调用非静态方法 * author: 百里 * Date: 2019/7/18 * Time: 17:28 */ function dump(...$var) { ...

  4. C# 静态方法调用非静态方法

    转载:http://blog.csdn.net/seattle1215/article/details/6657814 using System; using System.Collections.G ...

  5. PHP 类中静态方法调用非静态方法

    静态方法调用非静态方法: 在类中静态方法中,需要实例化对象,然后再调用类中的方法 非静态方法调用静态方法: 可以self 或者 类名加::的形式调用 如下面的案例: <?php class A{ ...

  6. JAVA Main方法中调用非静态方法

    在JAVA中静态方法中只能调用其他,静态方法.main方法都是静态方法,如果想调用其它的方法,要么只能是其它的静态方法.还有一种方法就是将当前类实例化在调用它的非静态方法 public class t ...

  7. PHP中静态(static)调用非静态方法详解--调用!!!

    来源:https://www.cnblogs.com/yolo-bean/p/7739265.html 这里分析了php面向对象中static静态属性和静态方法的调用.关于它们的调用(能不能调用,怎么 ...

  8. (转)为什么不能从静态的方法里面调用非静态方法,或变量and类加载机制

    1. 程序最终都将在内存中执行,变量只有在内存中占有一席之地时才能被访问. 类的静态成员(变量和方法)属于类本身,在类加载的时候就会分配内存,可以通过类名直接去访问:非静态成员(变量和方法)属于类的对 ...

  9. java静态方法调用非静态方法

    我们都知道,静态static方法中不能调用非静态non-static方法,准确地说是不能直接调用non-static方法.但是可以通过将一个对象的引用传入static方法中,再去调用该对象的non-s ...

随机推荐

  1. c# 访问Mysql

    下载Connector/Net驱动程序,并安装. 通过MySQLConnection对象来连接数据库,连接MySQL的程序的最前面需要引用MySql.Data.MySqlClient. using M ...

  2. http url转义字符,特殊字符

    空格 - %20 " - %22 # - %23 % - %25 & - %26 ( - %28 ) - %29 + - %2B , - %2C / - %2F : - %3A ; ...

  3. 在 Ubuntu16.04上安装并使用Docker

    介绍 Docker是一个开放源代码软件项目,让应用程序布署在软件容器下的工作可以自动化进行,借此在Linux操作系统上,提供一个额外的软件抽象层,以及操作系统层虚拟化的自动管理机制[1].Docker ...

  4. 【设计模式】C++单例模式的几种写法——Java自动加载内部类对象,C++怎么破?

    单例模式是最简单的设计模式,就让我像玩简单的游戏一样写下去吧. v1: 简单模式 和这个版本有过一面之缘,但不敢苟同. class Singleton { private: Singleton() { ...

  5. linux查看磁盘挂载的三种方法

    第一种方法:使用df命令,例如: orientalson:/home # df Filesystem 1K-blocks Used Available Use% Mounted on /dev/sda ...

  6. OpenCV 入门示例之四:一个简单的变换

    前言 图像的平滑处理,是计算机视觉中非常重要的操作,本文将展示一个可以对图像进行平滑处理的简单程序.而关于平滑处理深层次的知识,会在以后的文章中重点探讨. 代码示例 // 此头文件包含图像IO函数的声 ...

  7. TP框架---thinkphp基础知识

    php框架    发瑞 一.真实项目开发步骤: 多人同时开发项目,协作开发项目.分工合理.效率有提高(代码风格不一样.分工不好) 测试阶段 上线运行 对项目进行维护.修改.升级(单个人维护项目,十分困 ...

  8. 九度OJ 1010:A + B (字符串处理)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:7166 解决:3646 题目描述: 读入两个小于100的正整数A和B,计算A+B. 需要注意的是:A和B的每一位数字由对应的英文单词给出. ...

  9. wimdows安装mongodb,开机启动

    > d: > cd D:\Program Files\MongoDB\Server\3.0\bin > .\mongod --logpath "D:\Program Fil ...

  10. php soap使用示例

    soap_client.php <?php try { $client = new SoapClient( null, array('location' =>"http://lo ...