一. 魔术方法:
1. 魔术方法以“__”开头,是PHP的语法糖。语法糖是更实用的编码方式或技巧,使代码更易读。
2. __set与__get
<?php class Account{ private $user = 1 ; private $pwd = 2; public function __set($name,$value){ echo "Setting $name to $value \r\n"; $this ->$name = $value; } public function __get($name){ if (!isset($this->$name)){ echo 'no set '; $this->$name = 'set default value:'; } return $this->$name; } } $a = new Account(); echo $a -> user; echo "<br /><br />"; $a->user = 5; echo $a->$name; echo "<br /><br />"; echo $a->big;若类中定义了__set和__get魔术方法,那么当给对象赋值或取值时,既使属性不存在也不会报错。增强程序的健壮性。
<?php /* * 本代码没有执行成功 */ abstract class ActiveRecord{ protected static $table; protected $fieldValues; public $select; static function findById($id){ $query = "select * from " .static::$table ." where id = $id"; echo $query; return self::createDomain($query); } function __get($fieldname){ return $this->fieldvalues[$fieldname]; } static function __callStatic($method,$args){ $field = preg_replace('/^findBy(\w*)$','${1}',$method); $query = "select * from " .static::$table ." where $field='$args[0]"; return self::createDomain($query); } private static function createDomain($query){ echo "test"; $klass = get_called_class(); $domain = new $klass(); $domain->fieldvalues = array(); $domain->select = $query; foreach($klass::$fields as $field => $type){ $domain->fieldvalues[$field] = 'TODO:set from sql result'; } return $domain; } } class Customer extends ActiveRecord{ protected static $table = 'custdb'; protected static $fields = array( 'id' => 'int', 'email' => 'varchar', 'lastname' => 'varchar' ); public function __construct(){ echo "***"; } } class Sales extends ActiveRecord{ protected static $table = 'salesdb'; protected static $fields = array( 'id' => 'int', 'item' => 'varchar', 'qty' => 'int' ); } assert("select * from custdb where id = 123" == Customer::findById(123) ->select); assert("TODO: set from sql result" == Customer::findById(123)->email); assert("select * from salesdb where id = 321"== Sales::findById(321)->select); assert("select * from custdb where lastname = 'Denoncourt'"== Customer::findByLastname('Denoncourt')->select);使用__call与__callStatic可以‘防止调用不存在的方法而报错’。还可以使得方法的动态创建变为可能。
<?php header("Content-type: text/html; charset=utf-8"); class Account{ public $user = 1 ; private $pwd = 2 ; public function __toString(){ return "当前对象的用户是{$this->user},密码是{$this->pwd}"; } } $a = new Account(); echo $a; echo "<br /><br />"; echo PHP_EOL."==="; echo "<br /><br /><br />"; print_r($a);实际上,toString方法也是序列化的一种方式。
<?php header("Content-type: text/html; charset=utf-8"); class person{ public $name = 'Tom'; public $gender; static $money = 10000; public function __construct(){ echo "这里是父类",PHP_EOL; } public function say(){ echo $this->name,"\tis",$this->gender,"\r\n"; } } class family extends person{ public $name; public $gender; public $age; static $money = 100000; public function __construct(){ parent::__construct(); echo "这里是子类",PHP_EOL; } public function say(){ echo "<br />我说".$this->name,"\tis\t",$this->gender,",and is \t", $this->age,PHP_EOL."<br />"; } public function cry(){ echo parent::$money,PHP_EOL; echo "%>-<%",PHP_EOL; echo self::$money,PHP_EOL; echo "(*^_^*)"; } public function read(){ echo "<br /><br /><br />read again".parent::say()."<br />"; } } $poor = new family(); $poor->name = 'Lee'; $poor->gender = 'female'; $poor->age = 25; $poor->say(); $poor->cry(); $poor->read(); /* * 疑问: * 我在子类上加了个方法叫read * 结果执行结果成了: * 这里是父类 这里是子类 我说Lee is female,and is 25 10000 %>-<% 100000 (*^_^*)Lee isfemale read again 为什么read again在lee is female后面……(我感觉应该先执行read again) */
<?php class car{ public function addoil(){ echo "Add oil\r\n"; } } class bmw extends car{ } class benz{ public $car; public function __construct(){ $this->car = new car; } public function addoil(){ $this->car->addoil(); } } $bmw = new bmw(); $bmw ->addoil(); $benz = new benz(); $benz->addoil();使用继承的场景:
<?php header("Content-type: text/html; charset=utf-8"); class employee{ protected function working(){ echo "本方法需要重载才能运行"; } } class teacher extends employee{ public function working(){ echo "教书"; } } class coder extends employee{ public function working(){ echo "敲代码"; } } class readBooks extends employee{ public function working(){ echo "我不看书的!"; } } function doprint($obj){ if(get_class($obj) == 'employee'){ echo "error"; }else{ $obj->working(); } } doprint(new teacher()); doprint(new coder()); doprint(new employee()); doprint(new readBooks());通过接口可以实现多态。
版权声明:本文为博主原创文章,未经博主允许不得转载。
以上就介绍了(二)PHP面向对象理论2,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。