分享
 
 
 

PHP强制对象类型之instanceof操作符

王朝php·作者佚名  2006-11-24
窄屏简体版  字體: |||超大  

一、简介

在PHP中实现强制对象类型有时可能非常重要。如果缺少了它,或是因为缺乏这方面的知识——基于不正确的编程假设,或者仅仅是由于懒惰,那么你会在特定的Web应用程序中看到你所不希望的结果。特别是当用PHP 4进行编程时,使用"is_a()"函数(尽管还有其它方法)来验证你所使用的对象的类型是非常容易的事情。毫无疑问,强制对象类型还可以被用于过滤输入对象(需要被作为参数传递到同一个应用程序中的其它PHP类)。

不过,PHP 4并没有暴露一些有关于它的对象模型的弱点-为了实现某些在成熟的面向对象的语言中出现的特征,它偶而可能要求编写另外的代码。长时间以来,这一事实已经为PHP社区众所周知。然而,随着PHP 5的发行,许多这些极有价值的特征作为改进的对象模型的一部分被添加到其中。它们将有助于更为紧密地实现基于对象的代码的开发-允许你使用特定的对象特征。

在上面的情况下,当涉及到对象类型强制时应该特别注意。实际上,在一个Web应用程序的执行期间,PHP 5提供给开发者至少两种方法来检查对象类型——它们分别是“instanceof”操作符和“类型提示”特征。现在转到本文的主题,我将介绍PHP 5中"instanceof"操作符的使用;你很快就会发现,它可以非常方便地用来确定是否你正在使用的对象属于一个特定的类型。

本文将通过一些面向对象的示例来帮助你理解如何在PHP 5中实现强制对象类型。

二、 你不该做什么

为了展示在PHP 5中如何实现对象类型强制,我将使用(X)HTML widget类,还有一个简单的页面生成器类,并作了简单的修改以适合PHP 5开发环境。

我的第一个示例列举了一些派生自一个抽象的基类"HTMLElement"的(X)HTML widget类,它跳过了到它们的输入对象类型的检查。请先看下面的类:

//定义抽象类'HTMLElement'

abstract class HTMLElement{

protected $attributes;

protected function __construct($attributes){

if(!is_array($attributes)){

throw new Exception('Invalid attribute type');

}

$this->attributes=$attributes;

}

// 抽象的'getHTML()'方法

abstract protected function getHTML();

}

//定义具体的类'Div'-扩展HTMLElement

class Div extends HTMLElement{

private $output='<div ';

private $data;

public function __construct($attributes=array(),$data){

parent::__construct($attributes);

$this->data=$data;

}

//'getHTML()'方法的具体实现

public function getHTML(){

foreach($this->attributes as $attribute=>$value){

$this->output.=$attribute.'="'.$value.'" ';

}

$this->output=substr_replace($this->output,'>',-1);

$this->output.=$this->data.'</div>';

return $this->output;

}

}

//定义具体类'Header1'-扩展HTMLElement

class Header1 extends HTMLElement{

private $output='<h1 ';

private $data;

public function __construct($attributes=array(),$data){

parent::__construct($attributes);

$this->data=$data;

}

//'getHTML()'方法的具体的实现

public function getHTML(){

foreach($this->attributes as $attribute=>$value){

$this->output.=$attribute.'="'.$value.'" ';

}

$this->output=substr_replace($this->output,'>',-1);

$this->output.=$this->data.'</h1>';

return $this->output;

}

}

//定义具体类'Paragraph'-扩展HTMLElement

class Paragraph extends HTMLElement{

private $output='<p ';

private $data;

public function __construct($attributes=array(),$data){

parent::__construct($attributes);

$this->data=$data;

}

//'getHTML()'方法的具体实现

public function getHTML(){

foreach($this->attributes as $attribute=>$value){

$this->output.=$attribute.'="'.$value.'" ';

}

$this->output=substr_replace($this->output,'>',-1);

$this->output.=$this->data.'</p>';

return $this->output;

}

}

//定义具体类'UnorderedList'-扩展HTMLElement

class UnorderedList extends HTMLElement{

private $output='<ul ';

private $items=array();

public function __construct($attributes=array(),$items=array()){

parent::__construct($attributes);

if(!is_array($items)){

throw new Exception('Invalid parameter for list items');

}

$this->items=$items;

}

//'getHTML()'方法的具体实现

public function getHTML(){

foreach($this->attributes as $attribute=>$value){

$this->output.=$attribute.'="'.$value.'" ';

}

$this->output=substr_replace($this->output,'>',-1);

foreach($this->items as $item){

$this->output.='<li>'.$item.'</li>';

}

$this->output.='</ul>';

return $this->output;

}

}

如你所见,上面的(X)HTML widget类在生成一个网面中特定的元素时是非常有用的,但是我有意地把每一个类的代码写成这样,这样它们就不能够验证输入参数的有效性。你可能已经想到,输入参数将直接被传递到类构造器中并且作为属性赋值。问题出现了:这样做有什么错误吗?是的,有。现在,我将定义我的最简单的页面生成器类,并且用这样一些widget来填充(feed)它,这样你就可以看到这个类的输入是如何与不正确的对象相混杂。下面是该页面生成器类的签名:

class PageGenerator{

private $output='';

private $title;

public function __construct($title='Default Page'){

$this->title=$title;

}

public function doHeader(){

$this->output='<html><head><title>'.$this-

>title.'</title></head><body>';

}

public function addHTMLElement($htmlElement){

$this->output.=$htmlElement->getHTML();

}

public function doFooter(){

$this->output.='</body></html>';

}

public function fetchHTML(){

return $this->output;

}

}

现在,我们开始实例化一些(X)HTML widget对象,并且把它们传递到相应的生成器类,如下面的示例所示:

try{

//生成一些HTML元素

$h1=new Header1(array('name'=>'header1','class'=>'headerclass'),'Content for H1

element goes here');

$div=new Div(array('name'=>'div1','class'=>'divclass'),'Content for Div element

goes here');

$par=new Paragraph(array('name'=>'par1','class'=>'parclass'),'Content for Paragraph

element goes here');

$ul=new UnorderedList(array ('name'=>'list1','class'=>'listclass'),array

('item1'=>'value1','item2'=>'value2','item3'=>'value3'));

//实例化页面生成器类

$pageGen=new Page生成器();

$pageGen->doHeader();

// 添加'HTMLElement'对象

$pageGen->addHTMLElement($h1);

$pageGen->addHTMLElement($div);

$pageGen->addHTMLElement($par);

$pageGen->addHTMLElement($ul);

$pageGen->doFooter();

//显示网面

echo $pageGen->fetchHTML();

}

catch(Exception $e){

echo $e->getMessage();

exit();

}

在运行上面的PHP代码后,你所得到的结果是一个简单的网页-它包含一些前面创建的(X)HTML对象。这种情况下,如果因某些原因该网页生成器类收到一个不正确的对象并调用它的"addHTML()"方法,那么你很容易理解将会发生的事情。在此,我重新修改了这里的冲突条件-通过使用一个不存在的(X)HTML widget对象。请再次看一下下面的代码:

try{

//生成一些HTML元素

$h1=new Header1(array('name'=>'header1','class'=>'headerclass'),'Content for H1

element goes here');

$div=new Div(array('name'=>'div1','class'=>'divclass'),'Content for Div element

goes here');

$par=new Paragraph(array('name'=>'par1','class'=>'parclass'),'Content for Paragraph

element goes here');

$ul=new UnorderedList(array ('name'=>'list1','class'=>'listclass'),array

('item1'=>'value1','item2'=>'value2','item3'=>'value3'));

//实例化页面生成器类

$pageGen=new Page生成器();

$pageGen->doHeader();

//添加'HTMLElement'对象

$pageGen->addHTMLElement($fakeobj) //把并不存在的对象传递

到这个方法

$pageGen->addHTMLElement($div);

$pageGen->addHTMLElement($par);

$pageGen->addHTMLElement($ul);

$pageGen->doFooter();

// 显示网面

echo $pageGen->fetchHTML();

}

catch(Exception $e){

echo $e->getMessage();

exit();

}

在这种情况中,如下面一行所显示的:

$pageGen->addHTMLElement($fakeobj)//把不存在的对象传递到这个方法

一个并不存在的(X)HTML widget对象被传递到该页面生成器类,这样会导致一个致命性错误:

Fatal error: Call to a member function on a non-object in

path/to/file

怎么样?这就是对传递到生成器类的对象的类型不进行检查的直接惩罚!因此在编写你的脚本时一定要记住这个问题。幸好,还有一个简单的方案来解决这些问题,而且这也正是"instanceof"操作符的威力所在。如果你想要看一下这个操作符是如何使用的,请继续往下读吧。

三、 使用"instanceof"操作符

如你所见,"instanceof"操作符的使用非常简单,它用两个参数来完成其功能。第一个参数是你想要检查的对象,第二个参数是类名(事实上是一个接口名),用于确定是否这个对象是相应类的一个实例。当然,我故意使用了上面的术语,这样你就可以看到这个操作符的使用是多么直观。它的基本语法如下:

if (object instanceof class name){

//做一些有用的事情

}

现在,既然你已经了解了这个操作符在PHP 5是如何使用的,那么,为了验证被传递到它的"addHTMLElement()"方法的对象的类型,让我们再定义相应的网页生成器类。下面是这个类的新的签名,我在前面已经提到,它使用了"instanceof"操作符:

class PageGenerator{

private $output='';

private $title;

public function __construct($title='Default Page'){

$this->title=$title;

}

public function doHeader(){

$this->output='<html><head><title>'.$this->title.'</title></head><body>';

}

public function addHTMLElement($htmlElement){

if(!$htmlElement instanceof HTMLElement){

throw new Exception('Invalid (X)HTML element');

}

$this->output.=$htmlElement->getHTML();

}

public function doFooter(){

$this->output.='</body></html>';

}

public function fetchHTML(){

return $this->output;

}

}

请注意,在上面的类中,为了确定所有传递的对象是早些时候定义的"HTMLElement"类的实例,"instanceof"

[1] [2] 下一页

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有