PHP 重载 __call() _callStatic方法
在C++和java中,可以函数参数的个数或类型来进行重载。但php是弱类型的语言,无法采用传统的方法。若下面这样;
class Person{
function fun1($a)
{
echo 'fun1 '.$a.'<br/>';
}
function fun1($a,$b)
{
echo 'fun1 '.$a.' '.$b.' <br/>';
}
}
$t=new Person();
$t->fun1(1);
会报错:
Fatal error: Cannot redeclare PropertyTest::fun1()。
所以php采用了一套新的方法。
__call() is triggered when invoking inaccessible methods in an object context.
PHP5 的对象新增了一个专用方法 __call(),这个方法用来监视一个对象中的其它方法。如果你试着调用一个对象中不存在的方法,__call 方法将会被自动调用。
例七:__call
<?php
class foo {
function __call($name,$arguments) {
print("Did you call me? I'm $name!");
}
} $x = new foo();
$x->doStuff();
$x->fancy_stuff();
?>
这个特殊的方法可以被用来实现“过载(overloading)”的动作,这样你就可以检查你的参数并且通过调用一个私有的方法来传递参数。
例八:使用 __call 实现“过载”动作
<?php
class Magic {
function __call($name,$arguments) {
if($name=='foo') {
if(is_int($arguments[0])) $this->foo_for_int($arguments[0]);
if(is_string($arguments[0])) $this->foo_for_string($arguments[0]);
}
} private function foo_for_int($x) {
print("oh an int!");
} private function foo_for_string($x) {
print("oh a string!");
}
} $x = new Magic();
$x->foo(3);
$x->foo("3");
?>
引自:
_call和___callStatic这两个函数是php类 的默认函数,
__call() 在一个对象的上下文中,如果调用的方法不能访问,它将被触发
__callStatic() 在一个静态的上下文中,如果调用的方法不能访问,它将被触发
实例:
<?php
abstract class Obj
{
protected $property = array(); abstract protected function show(); public function __call($name,$value)
{
if(preg_match("/^set([a-z][a-z0-9]+)$/i",$name,$array))
{
$this->property[$array[1]] = $value[0];
return;
}
elseif(preg_match("/^get([a-z][a-z0-9]+)$/i",$name,$array))
{
return $this->property[$array[1]];
}
else
{
exit("<br>;Bad function name '$name' ");
} }
} class User extends Obj
{
public function show()
{
print ("Username: ".$this->property['Username']."<br>;");
//print ("Username: ".$this->getUsername()."<br>;");
print ("Sex: ".$this->property['Sex']."<br>;");
print ("Age: ".$this->property['Age']."<br>;");
}
} class Car extends Obj
{
public function show()
{
print ("Model: ".$this->property['Model']."<br>;");
print ("Sum: ".$this->property['Number'] * $this ->property['Price']."<br>;");
}
} $user = new User;
$user ->setUsername("Anny");
$user ->setSex("girl");
$user ->setAge(20);
$user ->show(); print("<br>;<br>;"); $car = new Car;
$car ->setModel("BW600");
$car ->setNumber(5);
$car ->setPrice(40000);
$car ->show();
?>
更多参考:hhttp://php.net/manual/zh/language.oop5.overloading.php 提供了很多例子。
http://www.garfieldtech.com/blog/magical-php-call
php 5.3 后新增了 __call 与__callStatic 魔法方法。
__call 当要调用的方法不存在或权限不足时,会自动调用__call 方法。
__callStatic 当调用的静态方法不存在或权限不足时,会自动调用__callStatic方法。
__call($funcname, $arguments)
__callStatic($funcname, $arguments)
参数说明:
$funcname String 调用的方法名称。
$arguments Array 调用方法时所带的参数。
__call 例子
<?php
class Member{
protected $memberdata = array();
public function __call($func, $arguments){
list($type, $name) = explode('_', $func);
if(!in_array($type, array('set','get')) || $name==''){
return '';
}
switch($type){
case 'set':
$this->memberdata[$name] = $arguments[];
break;
case 'get':
return isset($this->memberdata[$name])? $this->memberdata[$name] : '';
break;
default:
}
}
}
class User extends Member{
public function show(){
if($this->memberdata){
foreach($this->memberdata as $key=>$member){
echo $key.':'.$member.'<br>';
}
}
}
}
class Profession extends Member{
public function show(){
if($this->memberdata){
foreach($this->memberdata as $key=>$member){
echo $key.':'.$member.'<br>';
}
}
}
}
$userobj = new User();
$userobj->set_name('fdipzone');
$userobj->set_age();
$userobj->show();
$probj = new Profession();
$probj->set_profession('IT SERVICE');
$probj->set_price();
$probj->show();
?>
__callStatic例子
<?php
class Member{
protected static $memberdata = array();
public static function __callStatic($func, $arguments){
list($type, $name) = explode('_', $func);
if(!in_array($type, array('set','get')) || $name==''){
return '';
}
$feature = get_called_class();
switch($type){
case 'set':
self::$memberdata[$feature][$name] = $arguments[0];
break;
case 'get':
return isset(self::$memberdata[$feature][$name])? self::$memberdata[$feature][$name] : '';
break;
default:
}
}
}
class User extends Member{
public static function show(){
$feature = get_called_class();
if(self::$memberdata[$feature]){
foreach(self::$memberdata[$feature] as $key=>$member){
echo $key.':'.$member.'<br>';
}
}
}
}
class Profession extends Member{
public static function show(){
$feature = get_called_class();
if(self::$memberdata[$feature]){
foreach(self::$memberdata[$feature] as $key=>$member){
echo $key.':'.$member.'<br>';
}
}
}
}
User::set_name('fdipzone');
User::set_age(29);
User::show();
Profession::set_profession('IT SERVICE');
Profession::set_price(2500);
Profession::show();
?>
PHP 重载 __call() _callStatic方法的更多相关文章
- PHP面向对象_重载新的方法(parent::)
在学习PHP 这种语言中你会发现, PHP中的方法是不能重载的, 所谓的方法重载就是定义相同的方法名,通过“参数的个数“不同或“参数的类型“不 同,来访问我们的相同方法名的不同方法.但是因为PHP是弱 ...
- 【PHP面向对象(OOP)编程入门教程】12.重载新的方法(parent::)
在学习PHP 这种语言中你会发现, PHP中的方法是不能重载的, 所谓的方法重载就是定义相同的方法名,通过“参数的个数“不同或“参数的类型“不 同,来访问我们的相同方法名的不同方法.但是因为PHP是弱 ...
- 子类重载父类的方法“parent::方法名”转于 恩聪PHP学习教程
在PHP中不能定义重名的函数,也包括不能再同一个类中定义重名的方法,所以也就没有方法重载.单在子类中可以定义和父类重名的方法,因为父类的方法已经在子类中存在,这样在子类中就可以把从父类中继承过来的方法 ...
- Java学习笔记之方法重载,动态方法调度和抽象类
一.方法重载 如果子类中的方法与它的超类中的方法有相同的方法名,则称子类中的方法重载超类中的方法,特别是当超类和子类中的方法名和参数类型都相同时,在子类中调用该方法时,超类中的方法会被隐藏.考虑下面程 ...
- 子类重载父类的方法“parent:方法名”
在PHP中不能定义重名的函数,也包括不能再同一个类中定义重名的方法,所以也就没有方法重载.单在子类中可以定义和父类重名的方法,因为父类的方法已经在子类中存在,这样在子类中就可以把从父类中继承过来的方法 ...
- Java常见面试题02-方法重写和方法重载的区别?方法重载能改变返回值类型吗?
方法重写和方法重载的区别?方法重载能改变返回值类型吗? A:Override方法重写和Overload方法重载的区别? Overload是否可以改变返回值类型?可以 方法重写 • 子类中 ...
- PHP的重载及魔术方法
首先你要知道什么是php的魔术方法,它不是变魔术的,如果你想学习变魔术来错地方了哦! 定义:PHP 将所有以 __(两个下划线)开头的类方法保留为魔术方法.所以在定义类方法时,除了上述魔术方法,建议不 ...
- PHP的重载-使用魔术方法实现
摘录PHP官网对PHP重载的解释: PHP所提供的"重载"(overloading)是指动态地"创建"类属性和方法.我们是通过魔术方法(magic method ...
- Java编译器如何生成重载和覆盖方法代码
下面是一个很简单的例子,关于Java中的多态:方法重载和方法覆盖: 多态指的是方法在不同的时刻表现出不同的形式:在编译期间,这被叫做方法重载:方法重载允许相关的方法被同一个方法名字调用,这有时候被叫做 ...
随机推荐
- Loggerly技术架构
https://www.loggly.com/blog/topic/log-management-technology/
- Windows Azure 网站上的 WordPress 3.8
编辑人员注释:本文章由 Windows Azure 网站团队的项目经理 Sunitha Muthukrishna 和 Windows Azure 网站开发人员体验合作伙伴共同撰写. WordPr ...
- SVN使用技巧
安装 下载SVN服务端:VisualSVN Server https://www.visualsvn.com/downloads/ 安装,下一步...(更改地址,Location是安装目录,Repos ...
- Sql server 事务的两种用法
事务(Transaction)是并发控制的单位,是用户定义的一个操作序列.这些操作要么都做,要么都不做,是一个不可分割的工作单位. 通过事务,SQL Server能将逻辑相关的一组操作绑定在一起,以便 ...
- Java学习03
Java学习03 1.java面试一些问题 一.什么是变量 变量是指在程序执行期间可变的数据.类中的变量是用来表示累的属性的,在编程过程中,可以对变量的值进行修改.变量通常是可变的,即值是变化的 二. ...
- myeclipse 8.6 插件安装之SVN
在这里我要说明一点,myEclipse 8.6的插件安装和之前的版本可能会有一些区别,下面是SVN插件的安装: 1.从官网下载site-1.6.13.zip文件,网址是:subclipse.tigri ...
- ThinkPHP第五天(提交类型判定常量IS_POST等,错误页面种类,Model实例化方式,模板中使用函数,foreach循环,模板中.语法配置)
1.IS_GET.IS_POST.IS_PUT.IS_DELETE.IS_AJAX常量,方便快捷实现各个判断. 在Action类中还可以使用$this->isPost()等进行判断. 2.错误页 ...
- NSData 数据转换
NSData,数据,当我们需要把一些信息写入到文件里或发送到网络上,我们需要把这些数据转换下,变成纯粹的0.1字符流 数组转 NSData NSData *GLYtime = [NSKeyedArch ...
- The reference to entity "characterEncoding" must end with the ';' delimiter
数据源配置时加上编码转换格式后出问题了: The reference to entity "characterEncoding" must end with the ';' del ...
- QProcess与外部程序的调用(可以通过设置管道来交互)
项目做到一定阶段,经常需要在原来的工程上调用外部程序.Qt为此提供了QProcess类,QProcess可用于完成启动外部程序,并与之交互通信. 一.启动外部程序的两种方式:(1)一体式:void Q ...