今天在群里发现有人说,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. Sql 复习3之存储管理

    一.事务管理 单个工作单元称为事务,我们将若干条sql命令组合在一起,形成存储过程.触发器等,利用存储过程和触发器可以进行事务管理. 二.编程基础介绍 主要有:函数.程序设计语句等. 程序设计语句: ...

  2. Android 进程间通信——AIDL

    代码地址如下:http://www.demodashi.com/demo/12321.html 原文地址:http://blog.csdn.net/vnanyesheshou/article/deta ...

  3. XML完成小程序

    XML文档的格式如下: <?xml version="1.0" encoding="utf-8"?> <学生名单> <学生 Nam ...

  4. 各个DDR对比

    一.容量和封装相关 (1)逻辑Bank数量增加 DDR2 SDRAM中有4Bank和8Bank的设计,而DDR3起始的逻辑Bank是8个,另外还为未来的16个逻辑Bank做好了准备. (2)封装(Pa ...

  5. c#中Monitor的使用

    首先lock和Minitor有什么区别呢? 其实lock在IL代码中会被翻译成Monitor.也就是Monitor.Enter(obj)和Monitor.Exit(obj). lock(obj) { ...

  6. 深入Asyncio(十)异步解析式

    Async Comprehensions 目前已经学会了如何在Python中进行异步迭代,接下来的问题是这是否适用于解析式?答案是OJBK!该支持在PEP 530中提及,建议去读一下. >> ...

  7. java eclipse使用不同jdk版本

    因为开发需要,两个工程分别需要使用jdk1.6(elipse indigo)和jdk1.8(eclipse neon).因为两个eclipse对于jdk版本的要求不同,若只在环境变量中配置jdk版本, ...

  8. EasyNVR+EasyDSS实现简单套路的RTMP、微信直播、录像、回放方案

    安防领域HLS直播问题探讨 近期外出交流比较多,在之前的一篇博客<一种流量成本节省60%以上的手机直播微信直播H5直播幼儿园直播方案>我们说到了一种模式,就是当我们在做最近火热的幼儿园直播 ...

  9. poj 3071 Football <DP>

    链接:http://poj.org/problem?id=3071 题意: 有 2^n 支足球队,编号 1~2^n,现在给出每支球队打败其他球队的概率,问哪只球队取得冠军的概率最大? 思路: 设dp[ ...

  10. 504 Gateway Timeout Error 502 Bad Gateway

    总结 1. 502没有收到相应,或者收到了但不及时? cannot get a response in time 540收到了无效的响应 received an invalid response fr ...