ホームページ >バックエンド開発 >PHPチュートリアル >PHP のオブジェクトによって自動的に呼び出されるメソッド: set()、get()、tostring()
概要:
(1) __get($property_name): プライベート プロパティ $name の値を取得するとき、このオブジェクトは自動的にこのメソッドを呼び出し、プロパティ名の値をパラメーター $property_name に渡します。渡したプライベート プロパティの値。
(2) __set($property_name, $value): プライベート プロパティに値を直接割り当てる場合、このオブジェクトは自動的にこのメソッドを呼び出し、名前などのプロパティを $property_name に渡し、割り当てられる値を
" zhangsan" を $value に渡し、このメソッドを実行することで代入の目的は達成されます。(3) __tostring() : ハンドル(インスタンスとして理解できる)が直接出力されると、__tostring() メソッドが自動的に実行されます。
1.__ set()および__get()。ただし、属性の読み取りと割り当ての操作は非常に頻繁に行われるため、PHP5 では、属性の取得と割り当て、および属性の確認を行う 2 つの関数
"__get()" と "__set()" が事前定義されています。 )」と属性を削除するメソッド「__unset()」。
PHP5 には、属性の値を設定および取得するための特別なメソッド「__set()」と「__get()」が用意されています。これらの 2 つのメソッドは存在しません。デフォルトではですが、コンストラクター メソッド (__construct()) と同様に、これら 2 つのメソッドはクラスに追加された場合にのみ存在します。もちろん、次のように追加することもできます。また、個人的なスタイルに従って追加します。
rrree
__get() メソッド: このメソッドは、プライベート メンバー属性の値を取得するために使用されます。パラメーターは、必要なメンバー属性の名前で渡されます。 get を実行すると、取得された値が返されます。このメソッドを手動で呼び出す必要はありません。これは、このメソッドをプライベート メソッドにすることもでき、プライベート属性が直接取得されたときにオブジェクトによって自動的に呼び出されます。 private プロパティはカプセル化されているため、値を直接取得することはできません (例: "echo $p1->name" を直接取得するのは誤りです)。ただし、このメソッドをクラスに追加する場合は、「 「echo $p1->name」は値を直接取得し、__get($property_name) メソッドが自動的に呼び出され、このメソッドの内部実行を通じてプロパティ名がパラメータ $property_name に渡されます。渡した属性の値が返されます。メンバーのプロパティがプライベートとしてカプセル化されていない場合、オブジェクト自体はこのメソッドを自動的に呼び出しません。
__set() メソッド: このメソッドは、プライベート メンバー属性の値を設定するために使用されます。最初のパラメーターは値を設定する属性の名前で、2 番目のパラメーターは属性に設定する値。戻り値はありません。このメソッドは手動で呼び出す必要はなく、プライベート属性値を直接設定するときに自動的に呼び出されます。 __set() メソッドが存在しない場合は許可されません。例: $this->name='zhangsan' の場合、エラーが発生しますが、クラスに __set($property_name, $value) メソッドを追加すると、プライベート プロパティに値を直接割り当てることができます。呼び出されると自動的に呼び出され、$property_nameにnameなどの属性を渡し、$valueに代入する値「zhangsan」を渡します。このメソッドの実行により代入の目的は達成されます。メンバーのプロパティがプライベートとしてカプセル化されていない場合、オブジェクト自体はこのメソッドを自動的に呼び出しません。不正な値を渡さないように、このメソッドで判定することもできます。コードは次のとおりです:
<?phpclass Person { //下面是人的成员属性, 都是封装的私有成员 private $name; //人的名子 private $sex; //人的性别 private $age; //人的年龄 //__get()方法用来获取私有属性 public function __get($property_name) { echo "在直接获取私有属性值的时候,自动调用了这个__get()方法<br>"; if (isset ( $this->$property_name )) { return ($this->$property_name); } else { return (NULL); } } //__set()方法用来设置私有属性 public function __set($property_name, $value) { echo "在直接设置私有属性值的时候,自动调用了这个__set()方法为私有属性赋值<br>"; $this->$property_name = $value; }}$per=new person();$per->name="shirayner"; //此时$per自动调用__set($property_name, $value)方法echo $per->name; //此时$per自动调用__get($property_name)方法?>2.__tostring() TOstring(在这里故意这么写,是要说明PHP中方法不区分大小写,但实际开发中还需要注意规范)。当进行测试时,需要知道是否得出正确的数据。比如打印一个对象时,看看这个对象都有哪些属性,其值是什么,如果类定义了toString方法,就能在测试时,echo打印对象体,对象就会自动调用它所属类定义的toString方法,格式化输出这个对象所包含的数据。如果没有这个方法,那么echo一个对象将报错,例如“Catchable fatal error:Object of class Account could not be converted tostring”语法错误,实际上这是一个类型匹配失败错误。不过仍然可以用print_r()和var_dump()函数输出一个对象。当然,toString是可以定制的,所提供的信息和样式更丰富。
<?php
class Account{
public $user=1;
private $pwd=2;
// 自定义的格式化输出方法
public function toString(){
return "当前对象的用户名是{$this->user},密码是{$this->pwd}";
}
}
$a=new Account();
echo $a;
echo PHP_EOL;
print_r($a);
运行这段代码发现,使用toString方法后,输出的结果是可定制的,更易于理解。实际上,PHP的toString魔术方法的设计原型来源于 Java。Java中也有这么一个方法,而且在Java中,这个方法被大量使用,对于调试程序比较方便。实际上,toString方法也是一种序列化,我 们知道PHP自带serialize/unserialize也是进行序列化的,但是这组函数序列化时会产生一些无用信息,如属性字符串长度,造成存储空 间的无谓浪费。因此,可以实现自己的序列化和反序列化方法,或者json_encode/json_decode也是一个不错的选择。
为什么直接echo一个对象就会报语法错误,而如果这个对象实现toString方法后就可以直接输出呢?原因很简单,echo本来可以打印一个对 象,而且也实现了这个接口,但是PHP对其做了个限制,只有实现toString后才允许使用。从下面的PHP源代码里可以得到验证:
ZEND_VM_HANDLER(40, ZEND_ECHO, CONST|TMP|VAR|CV, ANY)
{
zend_op *opline = EX(opline);
zend_free_op free_op1;
zval z_copy;
zval *z = GET_OP1_ZVAL_PTR(BP_VAR_R);
// 此处的代码预留了把对象转换为字符串的接口
if (OP1_TYPE != IS_CONST &&
Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL &&
zend_std_cast_object_tostring(z, &z_copy, IS_STRING TSRMLS_CC) == SUCCESS) {
zend_print_variable(&z_copy);
zval_dtor(&z_copy);
} else {
zend_print_variable(z);
}
FREE_OP1();
ZEND_VM_NEXT_OPCODE();
}