fix(trait): preserve cross-instance method scope (fixes #67)
parent
24924673ec
commit
456f1a38b2
3 changed files with 137 additions and 22 deletions
@ -0,0 +1,53 @@ |
|||||||
|
--TEST-- |
||||||
|
Private, nested and aliased trait methods retain class scope across instances |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
|
||||||
|
trait NestedPrivateMethod |
||||||
|
{ |
||||||
|
private function nestedSecret(): string |
||||||
|
{ |
||||||
|
return 'nested'; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
trait NestedPrivateComposition |
||||||
|
{ |
||||||
|
use NestedPrivateMethod; |
||||||
|
} |
||||||
|
|
||||||
|
trait AliasMethodSource |
||||||
|
{ |
||||||
|
protected function sourceSecret(): string |
||||||
|
{ |
||||||
|
return 'alias'; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class PrivateTraitConsumer |
||||||
|
{ |
||||||
|
use NestedPrivateComposition; |
||||||
|
use AliasMethodSource { |
||||||
|
sourceSecret as private aliasSecret; |
||||||
|
} |
||||||
|
|
||||||
|
public function readOther(): string |
||||||
|
{ |
||||||
|
$other = new static(); |
||||||
|
return $other->nestedSecret() . ':' . $other->aliasSecret(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class PrivateTraitChild extends PrivateTraitConsumer |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
function main(): void |
||||||
|
{ |
||||||
|
echo (new PrivateTraitConsumer())->readOther(), "\n"; |
||||||
|
echo (new PrivateTraitChild())->readOther(), "\n"; |
||||||
|
} |
||||||
|
?> |
||||||
|
--EXPECT-- |
||||||
|
nested:alias |
||||||
|
nested:alias |
||||||
@ -0,0 +1,57 @@ |
|||||||
|
--TEST-- |
||||||
|
Trait-composed protected methods retain class scope across instances |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
|
||||||
|
trait CrossInstanceEvents |
||||||
|
{ |
||||||
|
protected function fire(string $event): string |
||||||
|
{ |
||||||
|
return 'base:' . $event; |
||||||
|
} |
||||||
|
|
||||||
|
protected function marker(): string |
||||||
|
{ |
||||||
|
return 'marker'; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class CrossInstanceBase |
||||||
|
{ |
||||||
|
use CrossInstanceEvents; |
||||||
|
|
||||||
|
public function touchSelf(): string |
||||||
|
{ |
||||||
|
$other = new self(); |
||||||
|
return $other->marker() . ':' . $other->fire('self'); |
||||||
|
} |
||||||
|
|
||||||
|
public function touchStatic(): string |
||||||
|
{ |
||||||
|
$other = new static(); |
||||||
|
return $other->marker() . ':' . $other->fire('static'); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class CrossInstanceChild extends CrossInstanceBase |
||||||
|
{ |
||||||
|
protected function fire(string $event): string |
||||||
|
{ |
||||||
|
return 'child:' . $event; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function main(): void |
||||||
|
{ |
||||||
|
$base = new CrossInstanceBase(); |
||||||
|
echo $base->touchSelf(), "\n"; |
||||||
|
echo $base->touchStatic(), "\n"; |
||||||
|
|
||||||
|
$child = new CrossInstanceChild(); |
||||||
|
echo $child->touchStatic(), "\n"; |
||||||
|
} |
||||||
|
?> |
||||||
|
--EXPECT-- |
||||||
|
marker:base:self |
||||||
|
marker:base:static |
||||||
|
marker:child:static |
||||||
Loading…
Reference in new issue