我遇到过这种情况很多次,但不确定为什么,所以让我感到好奇。有些类在声明之前就可以使用,而有些则不能;
例子1
$test = new TestClass(); // top of class
class TestClass {
function __construct() {
var_dump(__METHOD__);
}
}
输出
string 'TestClass::__construct' (length=22)
示例2
当一个类继承另一个类或实现任何接口时
$test = new TestClass(); // top of class
class TestClass implements JsonSerializable {
function __construct() {
var_dump(__METHOD__);
}
public function jsonSerialize() {
return json_encode(rand(1, 10));
}
}
输出
Fatal error: Class 'TestClass' not found
示例 3
让我们尝试使用相同的类,但更改位置。
class TestClass implements JsonSerializable {
function __construct() {
var_dump(__METHOD__);
}
public function jsonSerialize() {
return json_encode(rand(1, 10));
}
}
$test = new TestClass(); // move this from top to bottom
输出
string 'TestClass::__construct' (length=22)
示例4(我还测试了class_exists)
var_dump(class_exists("TestClass")); //true
class TestClass {
function __construct() {
var_dump(__METHOD__);
}
public function jsonSerialize() {
return null;
}
}
var_dump(class_exists("TestClass")); //true
一旦它实现了 JsonSerializable
(或其他任何接口)
var_dump(class_exists("TestClass")); //false
class TestClass implements JsonSerializable {
function __construct() {
var_dump(__METHOD__);
}
public function jsonSerialize() {
return null;
}
}
var_dump(class_exists("TestClass")); //true
还检查了没有 JsonSerializable 的操作码
line # * op fetch ext return operands
---------------------------------------------------------------------------------
3 0 > SEND_VAL 'TestClass'
1 DO_FCALL 1 $0 'class_exists'
2 SEND_VAR_NO_REF 6 $0
3 DO_FCALL 1 'var_dump'
4 4 NOP
14 5 > RETURN 1
同时检查具有 JsonSerializable 的操作码。
line # * op fetch ext return operands
---------------------------------------------------------------------------------
3 0 > SEND_VAL 'TestClass'
1 DO_FCALL 1 $0 'class_exists'
2 SEND_VAR_NO_REF 6 $0
3 DO_FCALL 1 'var_dump'
4 4 ZEND_DECLARE_CLASS $2 '%00testclass%2Fin%2FaDRGC0x7f563932f041', 'testclass'
5 ZEND_ADD_INTERFACE $2, 'JsonSerializable'
13 6 ZEND_VERIFY_ABSTRACT_CLASS $2
14 7 > RETURN 1
问题
Example 3
之所以能够工作是因为类在实例化之前被声明了,但为什么Example 1
一开始就能工作?- PHP中的扩展或接口继承如何工作,使得其中一个有效而另一个无效?
- 在示例4中到底发生了什么?
Opcodes
本来应该使事情更清晰,但由于在调用TestClass
之前调用了class_exists
,反过来了。
问题
- 为什么
Example 1
最初就能够工作? - PHP中的扩展或接口继承如何工作,使得其中一个有效而另一个无效?
- 在示例4中到底发生了什么?
Opcodes
事实上使问题更加复杂,因为class_exists
在调用TestClass
之前被调用,而不是相反。
Iterator
е’Ңзӣёе…ізҡ„зұ»дёӯдәҶи§ЈеҲ°дәҶиҝҷдёҖзӮ№гҖӮ - hakre