Method Dispatch ¶
There are differences between what Hack allows and what PHP (both HHVM and Zend) allows at runtime with respect to calling static and instance methods. Keeping them all straight can be confusing. Below are matrices that hopefully alleviate the pain of trying to remember the differences. The first matrix are calls from a class instance method. The second matrix represent calls from a class static method.
The code associated with the class instance method matrix is represented here:
<?hh
class A {
public function f1(): void {
echo "A.f1()\n";
}
public static function f2(): void {
echo "A.f2()\n";
}
}
class B extends A {
public function f1(): void {
echo "B.f1()\n";
}
public static function f2(): void {
echo "B.f2()\n";
}
public function test(): void {
$a = new A();
$c = new C();
A::f1();
$a->f1();
$a::f1();
A::f2();
$a->f2();
$a::f2();
self::f1();
B::f1();
self::f2();
B::f2();
C::f3();
$c->f3();
$c::f3();
C::f4();
$c->f4();
$c::f4();
parent::f1();
parent::f2();
static::f1();
static::f2();
$this->f1();
$this->f2();
}
}
class C {
public function f3(): void {
echo "C.f3()\n";
}
public static function f4(): void {
echo "C.f4()\n";
}
}
function main() {
$b = new B();
$b->test();
}
main();
And here is the output of the calls made in the instance test() function of class B.
Function Call
|
Zend Runtime Output
|
HHVM Runtime Output
|
Hack Output (partial)
|
Hack Output (strict)
|
A::f1();
|
A.f1()
|
A.f1()
|
Could not find static method f1. The closest thing is f1 but it's not a static method.
|
Could not find static method f1. The closest thing is f1 but it's not a static method.
|
$a->f1();
|
A.f1()
|
A.f1()
|
No error
|
No error
|
$a::f1();
|
A.f1()
|
A.f1()
|
No error
|
Don't use dynamic classes
|
A::f2();
|
A.f2()
|
A.f2()
|
No error
|
No error
|
$a->f2();
|
A.f2()
|
A.f2()
|
The method f2 is undefined in an object of type A. The closest thing isf2 but it's a static method.
|
The method f2 is undefined in an object of type A. The closest thing isf2 but it's a static method.
|
$a::f2();
|
A.f2()
|
A.f2()
|
No error
|
Don't use dynamic classes
|
self::f1();
|
B.f1()
|
B.f1()
|
Could not find static method f1. The closest thing is f1 but it's not a static method.
|
Could not find static method f1. The closest thing is f1 but it's not a static method.
|
B::f1();
|
B.f1()
|
B.f1()
|
Could not find static method f1. The closest thing is f1 but it's not a static method.
|
Could not find static method f1. The closest thing is f1 but it's not a static method.
|
self::f2();
|
B.f2()
|
B.f2()
|
No error
|
No error
|
B::f2();
|
B.f2()
|
B.f2()
|
No error
|
No error
|
C::f3();
|
C.f3()
|
C.f3()
|
Could not find static method f3. The closest thing is f3 but it's not a static method.
|
Could not find static method f3. The closest thing is f3 but it's not a static method.
|
$c->f3();
|
C.f3()
|
C.f3()
|
No error
|
No error
|
$c::f3();
|
C.f3()
|
C.f3()
|
No error
|
Don't use dynamic classes
|
C::f4();
|
C.f4()
|
C.f4()
|
No error
|
No error
|
$c->f4();
|
C.f4()
|
C.f4()
|
The method f4 is undefined in an object of type C. The closest thing isf4 but it's a static method.
|
The method f4 is undefined in an object of type C. The closest thing isf4 but it's a static method.
|
$c::f4();
|
C.f4()
|
C.f4()
|
No error
|
Don't use dynamic classes
|
parent::f1();
|
A.f1()
|
A.f1()
|
No error
|
No error
|
parent::f2();
|
A.f2()
|
A.f2()
|
The method f2 is undefined in an object of type A. The closest thing isf2 but it's a static method.
|
The method f2is undefine in an object of type A. The closest thing isf2 but it's a static method.
|
static::f1();
|
B.f1()
|
B.f1()
|
Could not find static method f1. The closest thing is f1 but it's not a static method.
|
Could not find static method f1. The closest thing is f1 but it's not a static method.
|
static::f2();
|
B.f2()
|
B.f2()
|
No error
|
No error
|
$this->f1();
|
B.f1()
|
B.f1()
|
No error
|
No error
|
$this->f2();
|
B.f2()
|
B.f2()
|
The method f2is undefined in an object of type B. The closest thing isf2 but it's a static method.
|
The method f2is undefined in an object of type B. The closest thing isf2 but it's a static method.
|
The code associated with the class static method matrix is represented here:
<?hh
class A {
public function f1(): void {
echo "A.f1()\n";
}
public static function f2(): void {
echo "A.f2()\n";
}
}
class B extends A {
public function f1(): void {
echo "B.f1()\n";
}
public static function f2(): void {
echo "B.f2()\n";
}
public static function stest(): void {
$a = new A();
$c = new C();
A::f1();
$a->f1();
$a::f1();
A::f2();
$a->f2();
$a::f2();
self::f1();
B::f1();
self::f2();
B::f2();
C::f3();
$c->f3();
$c::f3();
C::f4();
$c->f4();
$c::f4();
parent::f1();
parent::f2();
static::f1();
static::f2();
$this->f1();
$this->f2();
}
}
class C {
public function f3(): void {
echo "C.f3()\n";
}
public static function f4(): void {
echo "C.f4()\n";
}
}
function main() {
B::stest();
}
main();
And here is the output of the calls made in the static stest() function of class B.
Function Call
|
Zend Runtime Ouput
|
HHVM Runtime Output
|
Hack Output (partial)
|
Hack Output (strict)
|
A::f1();
|
A.f1()
|
A.f1()
|
Could not find static method f1. The closest thing is f1 but it's not a static method.
|
Could not find static method f1. The closest thing is f1 but it's not a static method.
|
$a->f1();
|
A.f1()
|
A.f1()
|
No error
|
No error
|
$a::f1();
|
A.f1()
|
A.f1()
|
No error
|
Don't use dynamic classes
|
A::f2();
|
A.f2()
|
A.f2()
|
No error
|
No error
|
$a->f2();
|
A.f2()
|
A.f2()
|
The method f2 is undefined in an object of type A. The closest thing is f2 but it's a static method.
|
The method f2 is undefined in an object of type A. The closest thing is f2 but it's a static method.
|
$a::f2();
|
A.f2()
|
A.f2()
|
No error
|
Don't use dynamic classes
|
self::f1();
|
B.f1()
|
B.f1()
|
Could not find static method f1. The closest thing is f1 but it's not a static method.
|
Could not find static method f1. The closest thing is f1 but it's not a static method.
|
B::f1();
|
B.f1()
|
B.f1()
|
Could not find static method f1. The closest thing is f1 but it's not a static method.
|
Could not find static method f1. The closest thing is f1 but it's not a static method.
|
self::f2();
|
B.f2()
|
B.f2()
|
No error
|
No error
|
B::f2();
|
B.f2()
|
B.f2()
|
No error
|
No error
|
C::f3();
|
C.f3()
|
C.f3()
|
Could not find static method f3. The closest thing is f3 but it's not a static method.
|
Could not find static method f3. The closest thing is f3 but it's not a static method.
|
$c->f3();
|
C.f3()
|
C.f3()
|
No error
|
No error
|
$c::f3();
|
C.f3()
|
C.f3()
|
No error
|
Don't use dynamic classes
|
C::f4();
|
C.f4()
|
C.f4()
|
No error
|
No error
|
$c->f4();
|
C.f4()
|
C.f4()
|
The method f4 is undefined in an object of type C. The closest thing is f4 but it's a static method.
|
The method f4 is undefined in an object of type C. The closest thing is f4 but it's a static method.
|
$c::f4();
|
C.f4()
|
C.f4()
|
No error
|
Don't use dynamic classes
|
parent::f1();
|
A.f1()
|
A.f1()
|
No error
|
No error
|
parent::f2();
|
A.f2()
|
A.f2()
|
The method f2 is undefined in an object of type A. The closest thing is f2 but it's a static method.
|
The method f2is undefined in an object of type A. The closest thing is f2 but it's a static method.
|
static::f1();
|
B.f1()
|
B.f1()
|
Could not find static method f1. The closest thing is f1 but it's not a static method.
|
Could not find static method f1. The closest thing is f1 but it's not a static method.
|
static::f2();
|
B.f2()
|
B.f2()
|
No error
|
No error
|
$this->f1();
|
Error. Using$this when not in object context.
|
HipHop Fatal error:$this isnull.
|
Do not use $this in a static method.
|
Do not use $this in a static method.
|
$this->f2();
|
Error. Using$this when not in object context.
|
HipHop Fatal error:$this isnull.
|
Do not use $this in a static method.
|
Do not use $this in a static method.
|
No comments:
Post a Comment