重载
2022-10-18 22:17:41重载
PHP所提供的"重载"(overloading)是指动态地"创建"类属性和方法。我们是通过 魔术方法(magic methods)来实现的。
当调用当前环境下未定义或不可见的类属性或方法时,重载方法会被调用。本节后面将使用 "不可访问成员(inaccessible members)"和"不可访问方法(inaccessible methods)"来称呼这些未定义或不可见的类属性或方法。
所有的重载方法都必须被声明为public。
Note:
这些魔术方法的参数都不能 通过引用传递。
Note:
PHP中的"重载"与其它绝大多数面向对象语言不同。传统的"重载"是用于提供多个同名的 类方法,但各方法的参数类型和个数不同。
更新日志
版本 说明
5.1.0 新增 __isset() 和 __unset()两个魔术方法.
5.3.0 新增 __callStatic()魔术方法. 可见性未设置为public或未声明为static的时候会产生一个警告
属性重载
void __set ( string $name , mixed $value ) mixed __get ( string $name ) bool __isset ( string $name ) void __unset ( string $name )
在给未定义的变量赋值时,__set() 会被调用。
读取未定义的变量的值时,__get() 会被调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | <code><?php class MemberTest { /** 被重载的数据保存在此 */ private $data = array (); /** 重载不能被用在已经定义的属性 */ public $declared = 1; /** 只有从类外部访问这个属性时,重载才会发生 */ private $hidden = 2; public function __set( $name , $value ) { echo "Setting '$name' to '$value' " ; $this ->data[ $name ] = $value ; } public function __get( $name ) { echo "Getting '$name' " ; if ( array_key_exists ( $name , $this ->data)) { return $this ->data[ $name ]; } $trace = debug_backtrace(); trigger_error( 'Undefined property via __get(): ' . $name . ' in ' . $trace [0][ 'file' ] . ' on line ' . $trace [0][ 'line' ], E_USER_NOTICE); return null; } /** PHP 5.1.0之后版本 */ public function __isset( $name ) { echo "Is '$name' set? " ; return isset( $this ->data[ $name ]); } /** PHP 5.1.0之后版本 */ public function __unset( $name ) { echo "Unsetting '$name' " ; unset( $this ->data[ $name ]); } /** 非魔术方法 */ public function getHidden() { return $this ->hidden; } } echo "<pre> " ; $obj = new MemberTest; $obj ->a = 1; echo $obj ->a . " " ; var_dump(isset( $obj ->a)); unset( $obj ->a); var_dump(isset( $obj ->a)); echo " " ; echo $obj ->declared . " " ; echo "Let's experiment with the private property named 'hidden': " ; echo "Privates are visible inside the class, so __get() not used... " ; echo $obj ->getHidden() . " " ; echo "Privates not visible outside of class, so __get() is used... " ; echo $obj ->hidden . " " ; ?></code> |
以上例程会输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | Setting 'a' to '1' Getting 'a' 1 Is 'a' set? bool(true) Unsetting 'a' Is 'a' set? bool(false) 1 Let 's experiment with the private property named ' hidden': Privates are visible inside the class , so __get() not used... 2 Privates not visible outside of class , so __get() is used... Getting 'hidden' Notice: Undefined property via __get(): hidden in <file> on line 70 in <file> on line 29 |
方法重载
mixed __call ( string $name , array $arguments ) mixed __callStatic ( string $name , array $arguments )当调用一个不可访问方法(如未定义,或者不可见)时,__call() 会被调用。
当在静态方法中调用一个不可访问方法(如未定义,或者不可见)时,__callStatic() 会被调用。
$name参数是要调用的方法名称。$arguments参数是一个数组,包含着要传递给方法的参数。
Example #2 使用 __call 和 ___callStatic 调用对象中的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <code><?php class MethodTest { public function __call( $name , $arguments ) { // 注意: $name 区分大小写 echo "Calling object method '$name' " . implode( ', ' , $arguments ). " " ; } /** PHP 5.3.0之后版本 */ public static function __callStatic( $name , $arguments ) { // Note: value of $name is case sensitive. echo "Calling static method '$name' " . implode( ', ' , $arguments ). " " ; } } $obj = new MethodTest; $obj ->runTest( 'in object context' ); MethodTest::runTest( 'in static context' ); // PHP 5.3.0之后版本 ?></code> |
以上例程会输出:
1 2 | Calling object method 'runTest' in object context Calling static method 'runTest' in static context |
当对未定义的变量调用isset() 或 empty()时,__isset() 会被调用。
当对未定义的变量调用unset()时,__unset() 会被调用。
参数$name是指要操作的变量名称。__set() 方法的$value 参数指定了$name变量的值。
属性重载只能在对象中进行。在静态方法中,这些魔术方法将不会被调用。所以这些方法都不能被 声明为static。
Example #1 使用__get, __set, __isset 和 __unset 进行重载