- 实现了 StaticPropertyFetch 类型检查方法 - 扩展了 ClassDef 构造函数以支持 flags 参数 - 添加了类继承时对 final 类的检查逻辑 - 更新了示例文件 call3.php 中的类结构 - 增加了多个类相关的测试用例文件 - 修改了后置操作解析逻辑以支持静态属性访问 - 在编译器基类中添加了类声明的错误处理 - 实现了对象包装器数组初始化 - 添加了对类可见性构造函数的支持测试 - 更新了接口定义的构造函数实现pull/1/head
parent
4ed56de30e
commit
25e567b3db
19 changed files with 614 additions and 17 deletions
@ -1,21 +1,33 @@ |
||||
<?php |
||||
class C |
||||
|
||||
class Circle |
||||
{ |
||||
function __call($name, $values) |
||||
function draw() |
||||
{ |
||||
$values[0][0] = 'changed'; |
||||
echo "Circle\n"; |
||||
} |
||||
} |
||||
function main() { |
||||
$a = array('original'); |
||||
$b = array('original'); |
||||
|
||||
$hack =& $b[0]; |
||||
|
||||
$c = new C; |
||||
$c->f($a); |
||||
$c->f($b); |
||||
class Square |
||||
{ |
||||
function draw() |
||||
{ |
||||
print "Square\n"; |
||||
} |
||||
} |
||||
|
||||
var_dump($a, $b); |
||||
function ShapeFactoryMethod($shape) |
||||
{ |
||||
switch ($shape) { |
||||
case "Circle": |
||||
return new Circle(); |
||||
case "Square": |
||||
return new Square(); |
||||
} |
||||
} |
||||
|
||||
function main() |
||||
{ |
||||
ShapeFactoryMethod("Circle")->draw(); |
||||
ShapeFactoryMethod("Square")->draw(); |
||||
} |
||||
@ -0,0 +1,84 @@ |
||||
--TEST-- |
||||
Classes general test |
||||
--FILE-- |
||||
<?php |
||||
|
||||
/* pretty nifty object-oriented code! */ |
||||
|
||||
class user { |
||||
public $first_name,$family_name,$address,$phone_num; |
||||
function display() |
||||
{ |
||||
echo "User information\n"; |
||||
echo "----------------\n\n"; |
||||
echo "First name:\t ".$this->first_name."\n"; |
||||
echo "Family name:\t ".$this->family_name."\n"; |
||||
echo "Address:\t ".$this->address."\n"; |
||||
echo "Phone:\t\t ".$this->phone_num."\n"; |
||||
echo "\n\n"; |
||||
} |
||||
function initialize($first_name,$family_name,$address,$phone_num) |
||||
{ |
||||
$this->first_name = $first_name; |
||||
$this->family_name = $family_name; |
||||
$this->address = $address; |
||||
$this->phone_num = $phone_num; |
||||
} |
||||
}; |
||||
|
||||
function test($u) |
||||
{ /* one can pass classes as arguments */ |
||||
$u->display(); |
||||
$t = $u; |
||||
$t->address = "New address..."; |
||||
return $t; /* and also return them as return values */ |
||||
} |
||||
|
||||
function main() { |
||||
$user1 = new user; |
||||
$user2 = new user; |
||||
|
||||
$user1->initialize("Zeev","Suraski","Ben Gourion 3, Kiryat Bialik, Israel","+972-4-8713139"); |
||||
$user2->initialize("Andi","Gutmans","Haifa, Israel","+972-4-8231621"); |
||||
$user1->display(); |
||||
$user2->display(); |
||||
|
||||
$tmp = test($user2); |
||||
$tmp->display(); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
User information |
||||
---------------- |
||||
|
||||
First name: Zeev |
||||
Family name: Suraski |
||||
Address: Ben Gourion 3, Kiryat Bialik, Israel |
||||
Phone: +972-4-8713139 |
||||
|
||||
|
||||
User information |
||||
---------------- |
||||
|
||||
First name: Andi |
||||
Family name: Gutmans |
||||
Address: Haifa, Israel |
||||
Phone: +972-4-8231621 |
||||
|
||||
|
||||
User information |
||||
---------------- |
||||
|
||||
First name: Andi |
||||
Family name: Gutmans |
||||
Address: Haifa, Israel |
||||
Phone: +972-4-8231621 |
||||
|
||||
|
||||
User information |
||||
---------------- |
||||
|
||||
First name: Andi |
||||
Family name: Gutmans |
||||
Address: New address... |
||||
Phone: +972-4-8231621 |
||||
@ -0,0 +1,23 @@ |
||||
--TEST-- |
||||
ZE2 A final class cannot be inherited |
||||
--SKIPIF-- |
||||
<?php die('skip'); ?> |
||||
--FILE-- |
||||
<?php |
||||
|
||||
final class base { |
||||
function show() { |
||||
echo "base\n"; |
||||
} |
||||
} |
||||
|
||||
class derived extends base { |
||||
} |
||||
|
||||
function main() { |
||||
$t = new base(); |
||||
echo "Done\n"; // shouldn't be displayed |
||||
} |
||||
?> |
||||
--EXPECTF-- |
||||
Fatal error: Class derived cannot extend final class base in %s on line %d |
||||
@ -0,0 +1,13 @@ |
||||
--TEST-- |
||||
Instantiate stdClass |
||||
--FILE-- |
||||
<?php |
||||
function main() { |
||||
$obj = new stdClass; |
||||
echo get_class($obj)."\n"; |
||||
echo "Done\n"; |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
stdClass |
||||
Done |
||||
@ -0,0 +1,43 @@ |
||||
--TEST-- |
||||
ZE2 object cloning, 1 |
||||
--FILE-- |
||||
<?php |
||||
class test { |
||||
public $p1 = 1; |
||||
public $p2 = 2; |
||||
public $p3; |
||||
}; |
||||
|
||||
function main() { |
||||
$obj = new test; |
||||
$obj->p2 = 'A'; |
||||
$obj->p3 = 'B'; |
||||
$copy = clone $obj; |
||||
$copy->p3 = 'C'; |
||||
echo "Object\n"; |
||||
var_dump($obj); |
||||
echo "Clown\n"; |
||||
var_dump($copy); |
||||
echo "Done\n"; |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
Object |
||||
object(test)#1 (3) { |
||||
["p1"]=> |
||||
int(1) |
||||
["p2"]=> |
||||
string(1) "A" |
||||
["p3"]=> |
||||
string(1) "B" |
||||
} |
||||
Clown |
||||
object(test)#2 (3) { |
||||
["p1"]=> |
||||
int(1) |
||||
["p2"]=> |
||||
string(1) "A" |
||||
["p3"]=> |
||||
string(1) "C" |
||||
} |
||||
Done |
||||
@ -0,0 +1,44 @@ |
||||
--TEST-- |
||||
ZE2 object cloning, 2 |
||||
--FILE-- |
||||
<?php |
||||
class test { |
||||
public $p1 = 1; |
||||
public $p2 = 2; |
||||
public $p3; |
||||
public function __clone() { |
||||
} |
||||
}; |
||||
function main() { |
||||
$obj = new test; |
||||
$obj->p2 = 'A'; |
||||
$obj->p3 = 'B'; |
||||
$copy = clone $obj; |
||||
$copy->p3 = 'C'; |
||||
echo "Object\n"; |
||||
var_dump($obj); |
||||
echo "Clown\n"; |
||||
var_dump($copy); |
||||
echo "Done\n"; |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
Object |
||||
object(test)#1 (3) { |
||||
["p1"]=> |
||||
int(1) |
||||
["p2"]=> |
||||
string(1) "A" |
||||
["p3"]=> |
||||
string(1) "B" |
||||
} |
||||
Clown |
||||
object(test)#2 (3) { |
||||
["p1"]=> |
||||
int(1) |
||||
["p2"]=> |
||||
string(1) "A" |
||||
["p3"]=> |
||||
string(1) "C" |
||||
} |
||||
Done |
||||
@ -0,0 +1,57 @@ |
||||
--TEST-- |
||||
ZE2 object cloning, 3 |
||||
--FILE-- |
||||
<?php |
||||
class base { |
||||
protected $p1 = 'base:1'; |
||||
public $p2 = 'base:2'; |
||||
public $p3 = 'base:3'; |
||||
public $p4 = 'base:4'; |
||||
public $p5 = 'base:5'; |
||||
private $p6 = 'base:6'; |
||||
public function __clone() { |
||||
} |
||||
}; |
||||
|
||||
class test extends base { |
||||
public $p1 = 'test:1'; |
||||
public $p3 = 'test:3'; |
||||
public $p4 = 'test:4'; |
||||
public $p5 = 'test:5'; |
||||
public function __clone() { |
||||
$this->p5 = 'clone:5'; |
||||
} |
||||
} |
||||
function main() { |
||||
$obj = new test; |
||||
$obj->p4 = 'A'; |
||||
$copy = clone $obj; |
||||
echo "Object\n"; |
||||
print_r($obj); |
||||
echo "Clown\n"; |
||||
print_r($copy); |
||||
echo "Done\n"; |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
Object |
||||
test Object |
||||
( |
||||
[p1] => test:1 |
||||
[p2] => base:2 |
||||
[p3] => test:3 |
||||
[p4] => A |
||||
[p5] => test:5 |
||||
[p6:base:private] => base:6 |
||||
) |
||||
Clown |
||||
test Object |
||||
( |
||||
[p1] => test:1 |
||||
[p2] => base:2 |
||||
[p3] => test:3 |
||||
[p4] => A |
||||
[p5] => clone:5 |
||||
[p6:base:private] => base:6 |
||||
) |
||||
Done |
||||
@ -0,0 +1,83 @@ |
||||
--TEST-- |
||||
ZE2 object cloning, 4 |
||||
--FILE-- |
||||
<?php |
||||
abstract class base { |
||||
public $a = 'base'; |
||||
|
||||
// disallow cloning |
||||
private function __clone() {} |
||||
} |
||||
|
||||
class test extends base { |
||||
public $b = 'test'; |
||||
|
||||
// re-enable cloning |
||||
public function __clone() {} |
||||
|
||||
public function show() { |
||||
var_dump($this); |
||||
} |
||||
} |
||||
function main() { |
||||
echo "Original\n"; |
||||
$o1 = new test; |
||||
$o1->a = array(1,2); |
||||
$o1->b = array(3,4); |
||||
$o1->show(); |
||||
|
||||
echo "Clone\n"; |
||||
$o2 = clone $o1; |
||||
$o2->show(); |
||||
|
||||
echo "Modify\n"; |
||||
$o2->a = 5; |
||||
$o2->b = 6; |
||||
$o2->show(); |
||||
|
||||
echo "Done\n"; |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
Original |
||||
object(test)#1 (2) { |
||||
["a"]=> |
||||
array(2) { |
||||
[0]=> |
||||
int(1) |
||||
[1]=> |
||||
int(2) |
||||
} |
||||
["b"]=> |
||||
array(2) { |
||||
[0]=> |
||||
int(3) |
||||
[1]=> |
||||
int(4) |
||||
} |
||||
} |
||||
Clone |
||||
object(test)#2 (2) { |
||||
["a"]=> |
||||
array(2) { |
||||
[0]=> |
||||
int(1) |
||||
[1]=> |
||||
int(2) |
||||
} |
||||
["b"]=> |
||||
array(2) { |
||||
[0]=> |
||||
int(3) |
||||
[1]=> |
||||
int(4) |
||||
} |
||||
} |
||||
Modify |
||||
object(test)#2 (2) { |
||||
["a"]=> |
||||
int(5) |
||||
["b"]=> |
||||
int(6) |
||||
} |
||||
Done |
||||
@ -0,0 +1,24 @@ |
||||
--TEST-- |
||||
ZE2 object cloning, 5 |
||||
--SKIPIF-- |
||||
<?php die('skip, failed at compile time'); ?> |
||||
--FILE-- |
||||
<?php |
||||
abstract class base { |
||||
public $a = 'base'; |
||||
|
||||
// disallow cloning once forever |
||||
final protected function __clone() {} |
||||
} |
||||
|
||||
class test extends base { |
||||
// reenabling should fail |
||||
public function __clone() {} |
||||
} |
||||
|
||||
function main() { |
||||
|
||||
} |
||||
?> |
||||
--EXPECTF-- |
||||
Fatal error: Cannot override final method base::__clone() in %sclone_005.php on line 11 |
||||
@ -0,0 +1,39 @@ |
||||
--TEST-- |
||||
ZE2 object cloning, 6 |
||||
--INI-- |
||||
error_reporting=2047 |
||||
--FILE-- |
||||
<?php |
||||
|
||||
class MyCloneable { |
||||
static $id = 0; |
||||
|
||||
function __construct() { |
||||
$this->id = self::$id++; |
||||
} |
||||
|
||||
function __clone() { |
||||
$this->address = "New York"; |
||||
$this->id = self::$id++; |
||||
} |
||||
} |
||||
function main() { |
||||
$original = new MyCloneable(); |
||||
|
||||
$original->name = "Hello"; |
||||
$original->address = "Tel-Aviv"; |
||||
|
||||
echo $original->id . "\n"; |
||||
|
||||
$clone = clone $original; |
||||
|
||||
echo $clone->id . "\n"; |
||||
echo $clone->name . "\n"; |
||||
echo $clone->address . "\n"; |
||||
} |
||||
?> |
||||
--EXPECTF-- |
||||
0 |
||||
1 |
||||
Hello |
||||
New York |
||||
@ -0,0 +1,76 @@ |
||||
--TEST-- |
||||
ZE2 A private constructor cannot be called |
||||
--SKIPIF-- |
||||
<?php die('skip'); ?> |
||||
--FILE-- |
||||
<?php |
||||
|
||||
class Test |
||||
{ |
||||
function __construct() |
||||
{ |
||||
echo __METHOD__ . "()\n"; |
||||
} |
||||
} |
||||
|
||||
class Derived extends Test |
||||
{ |
||||
function __construct() |
||||
{ |
||||
echo __METHOD__ . "()\n"; |
||||
parent::__construct(); |
||||
} |
||||
|
||||
static function f() |
||||
{ |
||||
new Derived; |
||||
} |
||||
} |
||||
|
||||
|
||||
class TestPriv |
||||
{ |
||||
private function __construct() |
||||
{ |
||||
echo __METHOD__ . "()\n"; |
||||
} |
||||
|
||||
static function f() |
||||
{ |
||||
new TestPriv; |
||||
} |
||||
} |
||||
|
||||
|
||||
class DerivedPriv extends TestPriv |
||||
{ |
||||
function __construct() |
||||
{ |
||||
echo __METHOD__ . "()\n"; |
||||
parent::__construct(); |
||||
} |
||||
|
||||
static function f() |
||||
{ |
||||
new DerivedPriv; |
||||
} |
||||
} |
||||
|
||||
function main() { |
||||
Derived::f(); |
||||
TestPriv::f(); |
||||
DerivedPriv::f(); |
||||
} |
||||
?> |
||||
--EXPECTF-- |
||||
Derived::__construct() |
||||
Test::__construct() |
||||
TestPriv::__construct() |
||||
DerivedPriv::__construct() |
||||
|
||||
Fatal error: Uncaught Error: Cannot call private TestPriv::__construct() in %sctor_visibility.php:%d |
||||
Stack trace: |
||||
#0 %s(%d): DerivedPriv->__construct() |
||||
#1 %s(%d): DerivedPriv::f() |
||||
#2 {main} |
||||
thrown in %sctor_visibility.php on line %d |
||||
@ -0,0 +1,35 @@ |
||||
--TEST-- |
||||
ZE2 dereferencing of objects from methods |
||||
--SKIPIF-- |
||||
<?php die('skip'); ?> |
||||
--FILE-- |
||||
<?php |
||||
|
||||
class Name { |
||||
function __construct(public string $name) {} |
||||
|
||||
function display() { |
||||
echo $this->name . "\n"; |
||||
} |
||||
} |
||||
|
||||
class Person { |
||||
private $name; |
||||
|
||||
function __construct($_name, $_address) { |
||||
$this->name = new Name($_name); |
||||
} |
||||
|
||||
function getName() { |
||||
return $this->name; |
||||
} |
||||
} |
||||
|
||||
function main() { |
||||
$person = new Person("John", "New York"); |
||||
$person->getName()->display(); |
||||
} |
||||
|
||||
?> |
||||
--EXPECT-- |
||||
John |
||||
@ -0,0 +1,24 @@ |
||||
--TEST-- |
||||
ZE2 Destructors and echo |
||||
--FILE-- |
||||
<?php |
||||
|
||||
class Test |
||||
{ |
||||
function __construct() { |
||||
echo __METHOD__ . "\n"; |
||||
} |
||||
|
||||
function __destruct() { |
||||
echo __METHOD__ . "\n"; |
||||
} |
||||
} |
||||
|
||||
function main() { |
||||
$o = new Test; |
||||
} |
||||
|
||||
?> |
||||
--EXPECT-- |
||||
Test::__construct |
||||
Test::__destruct |
||||
Loading…
Reference in new issue