- 正确处理 parent::、self:: 和 static:: 的常量引用与类型解析 - 支持 ::class 魔法常量的编译期求值与字符串类型推断 - 引用其他类常量时继承其实际类型,避免误判为 VAR - 仅当父类常量有显式声明类型时才校验类型兼容性 - 运行时注册子类常量前先删除父类继承条目以避免重定义冲突pull/27/head
parent
559a8860a0
commit
a1b09926a3
8 changed files with 222 additions and 20 deletions
@ -0,0 +1,51 @@ |
|||||||
|
--TEST-- |
||||||
|
class const override variants (self::class, parent::class, references, multi-level) |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
|
||||||
|
declare(strict_types=1); |
||||||
|
|
||||||
|
class Base |
||||||
|
{ |
||||||
|
public const NAME = 'Base'; |
||||||
|
public const GREETING = 'hello'; |
||||||
|
public const VALUE = 42; |
||||||
|
} |
||||||
|
|
||||||
|
class Other |
||||||
|
{ |
||||||
|
public const TAG = 'other'; |
||||||
|
} |
||||||
|
|
||||||
|
class Mid extends Base |
||||||
|
{ |
||||||
|
public const NAME = Base::GREETING; // 'hello' |
||||||
|
public const SELF_NAME = self::class; // 'Mid' |
||||||
|
public const PARENT_NAME = parent::class; // 'Base' |
||||||
|
public const CROSS = Other::TAG; // 'other' |
||||||
|
} |
||||||
|
|
||||||
|
class Leaf extends Mid |
||||||
|
{ |
||||||
|
public const VALUE = Mid::NAME; // 'hello' (overrides Base::VALUE int with a string) |
||||||
|
public const LEAF_NAME = self::class; // 'Leaf' |
||||||
|
public const GREET = Base::GREETING; // 'hello' |
||||||
|
} |
||||||
|
|
||||||
|
function main() |
||||||
|
{ |
||||||
|
var_dump(Mid::NAME, Mid::SELF_NAME, Mid::PARENT_NAME, Mid::CROSS); |
||||||
|
var_dump(Leaf::VALUE, Leaf::LEAF_NAME, Leaf::GREET); |
||||||
|
var_dump(Base::VALUE, Leaf::VALUE); |
||||||
|
} |
||||||
|
?> |
||||||
|
--EXPECT-- |
||||||
|
string(5) "hello" |
||||||
|
string(3) "Mid" |
||||||
|
string(4) "Base" |
||||||
|
string(5) "other" |
||||||
|
string(5) "hello" |
||||||
|
string(4) "Leaf" |
||||||
|
string(5) "hello" |
||||||
|
int(42) |
||||||
|
string(5) "hello" |
||||||
@ -0,0 +1,30 @@ |
|||||||
|
--TEST-- |
||||||
|
class const override referencing another constant |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
|
||||||
|
declare(strict_types=1); |
||||||
|
|
||||||
|
abstract class ParentClass |
||||||
|
{ |
||||||
|
public const A = 'A'; |
||||||
|
public const B = 'B'; |
||||||
|
} |
||||||
|
|
||||||
|
class TestClass extends ParentClass |
||||||
|
{ |
||||||
|
public const A = ParentClass::B; |
||||||
|
public const B = 'bbb'; |
||||||
|
} |
||||||
|
|
||||||
|
function main() |
||||||
|
{ |
||||||
|
var_dump(ParentClass::A, ParentClass::B); |
||||||
|
var_dump(TestClass::A, TestClass::B); |
||||||
|
} |
||||||
|
?> |
||||||
|
--EXPECT-- |
||||||
|
string(1) "A" |
||||||
|
string(1) "B" |
||||||
|
string(1) "B" |
||||||
|
string(3) "bbb" |
||||||
Loading…
Reference in new issue