PHP强迫对象类型之instanceof操纵符
核心提示:PHP编程,PHP教程,PHP5教程,PHP开发
1、简介在PHP中实现强迫对象类型有时可能非常重要。假设缺少了它,或是由于缺少这方面的知识——基于不正确的编程假定,或仅仅是由于怠惰,那末你会在特定的Web利用程序中看到你所不希看的结果。特别是当用PHP4进行编程时,使用"is_a()"函数(虽然还有其它方法)来验证你所使用的对象的类型是非常轻易的事情。毫无疑问,强迫对象类型还可以被用于过滤输进对象(需要被作为参数传递到同1个利用程序中的其它PHP类)。
不过,PHP4并没有暴露1些有关于它的对象模型的弱点-为了实现某些在成熟的面向对象的语言中出现的特点,它偶而可能要求编写另外的代码。长时间以来,这1事实已为PHP社区尽人皆知。但是,随着PHP5的发行,很多这些极有价值的特点作为改进的对象模型的1部份被添加到其中。它们将有助于更加紧密地实现基于对象的代码的开发-答应你使用特定的对象特点。
在上面的情况下,当触及到对象类型强迫时应当特别留意。实际上,在1个Web利用程序的履行期间,PHP5提供给开发者最少两种方法来检查对象类型——它们分别是“instanceof”操纵符和“类型提示”特点。现在转到本文的主题,我将先容PHP5中"instanceof"操纵符的使用;你很快就会发现,它可以非常方便地用来肯定是否是你正在使用的对象属于1个特定的类型。
本文将通过1些面向对象的示例来帮助你理解如何在PHP5中实现强迫对象类型。
2、你不该做甚么
为了展现在PHP5中如何实现对象类型强迫,我将使用(X)HTMLwidget类,还有1个简单的页面天生器类,并作了简单的修改以合适PHP5开发环境。
我的第1个示例罗列了1些派生自1个抽象的基类"HTMLElement"的(X)HTMLwidget类,它跳过了到它们的输进对象类型的检查。请先看下面的类:
abstractclassHTMLElement{
protected$attributes;
protectedfunction__construct($attributes){
if(!is_array($attributes)){
thrownewException('Invalidattributetype');
}
$this->attributes=$attributes;
}
//抽象的'getHTML()'方法
abstractprotectedfunctiongetHTML();
}
//定义具体的类'Div'-扩大HTMLElement
classDivextendsHTMLElement{
private$output='<div';
private$data;
publicfunction__construct($attributes=array(),$data){
parent::__construct($attributes);
$this->data=$data;
}
//'getHTML()'方法的具体实现
publicfunctiongetHTML(){
foreach($this->attributesas$attribute=>$value){
$this->output.=$attribute.'="'.$value.'"';
}
$this->output=substr_replace($this->output,'>',⑴);
$this->output.=$this->data.'</div>';
return$this->output;
}
}
//定义具体类'Header1'-扩大HTMLElement
classHeader1extendsHTMLElement{
private$output='<h1';
private$data;
publicfunction__construct($attributes=array(),$data){
parent::__construct($attributes);
$this->data=$data;
}
//'getHTML()'方法的具体的实现
publicfunctiongetHTML(){
foreach($this->attributesas$attribute=>$value){
$this->output.=$attribute.'="'.$value.'"';
}
$this->output=substr_replace($this->output,'>',⑴);
$this->output.=$this->data.'</h1>';
return$this->output;
}
}
//定义具体类'Paragraph'-扩大HTMLElement
classParagraphextendsHTMLElement{
private$output='<p';
private$data;
publicfunction__construct($attributes=array(),$data){
parent::__construct($attributes);
$this->data=$data;
}
//'getHTML()'方法的具体实现
publicfunctiongetHTML(){
foreach($this->attributesas$attribute=>$value){
$this->output.=$attribute.'="'.$value.'"';
}
$this->output=substr_replace($this->output,'>',⑴);
$this->output.=$this->data.'</p>';
return$this->output;
}
}
//定义具体类'UnorderedList'-扩大HTMLElement
classUnorderedListextendsHTMLElement{
private$output='<ul';
private$items=array();
publicfunction__construct($attributes=array(),$items=array()){
parent::__construct($attributes);
if(!is_array($items)){
thrownewException('Invalidparameterforlistitems');
}
$this->items=$items;
}
//'getHTML()'方法的具体实现
publicfunctiongetHTML(){
foreach($this->attributesas$attribute=>$value){
$this->output.=$attribute.'="'.$value.'"';
}
$this->output=substr_replace($this->output,'>',⑴);
foreach($this->itemsas$item){
$this->output.='<li>'.$item.'</li>';
}
$this->output.='</ul>';
return$this->output;
}
}
如你所见,上面的(X)HTMLwidget类在天生1个网面中特定的元素时是非常有用的,但是我故意地把每1个类的代码写成这样,这样它们就不能够验证输进参数的有效性。你可能已想到,输进参数将直接被传递到类构造器中并且作为属性赋值。题目出现了:这样做有甚么毛病吗?是的,有。现在,我将定义我的最简单的页面天生器类,并且用这样1些widget来填充(feed)它,这样你便可以够看到这个类的输进是如何与不正确的对象相混杂。下面是该页面天生器类的签名:
private$output='';
private$title;
publicfunction__construct($title='DefaultPage'){
$this->title=$title;
}
publicfunctiondoHeader(){
$this->output='<html><head><title>'.$this-
>title.'</title></head><body>';
}
publicfunctionaddHTMLElement($htmlElement){
$this->output.=$htmlElement->getHTML();
}
publicfunctiondoFooter(){
$this->output.='</body></html>';
}
publicfunctionfetchHTML(){
return$this->output;
}
}
现在,我们开始实例化1些(X)HTMLwidget对象,并且把它们传递到相应的天生器类,以下面的示例所示:
//天生1些HTML元素
$h1=newHeader1(array('name'=>'header1','class'=>'headerclass'),'ContentforH1
elementgoeshere');
$div=newDiv(array('name'=>'div1','class'=>'divclass'),'ContentforDivelement
goeshere');
$par=newParagraph(array('name'=>'par1','class'=>'parclass'),'ContentforParagraph
elementgoeshere');
$ul=newUnorderedList(array('name'=>'list1','class'=>'listclass'),array
('item1'=>'value1','item2'=>'value2','item3'=>'value3'));
//实例化页面天生器类
$pageGen=newPage天生器();
$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代码后,你所得到的结果是1个简单的网页-它包括1些前面创建的(X)HTML对象。这类情况下,假设因某些缘由该网页天生器类收到1个不正确的对象并调用它的"addHTML()"方法,那末你很轻易理解将会产生的事情。在此,我重新修改了这里的冲突条件-通过使用1个不存在的(X)HTMLwidget对象。请再次看1下下面的代码:
//天生1些HTML元素
$h1=newHeader1(array('name'=>'header1','class'=>'headerclass'),'ContentforH1
elementgoeshere');
$div=newDiv(array('name'=>'div1','class'=>'divclass'),'ContentforDivelement
goeshere');
$par=newParagraph(array('name'=>'par1','class'=>'parclass'),'ContentforParagraph
elementgoeshere');
$ul=newUnorderedList(array('name'=>'list1','class'=>'listclass'),array
('item1'=>'value1','item2'=>'value2','item3'=>'value3'));
//实例化页面天生器类
$pageGen=newPage天生器();
$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();
}
在这类情况中,以下面1行所显示的:
1个其实不存在的(X)HTMLwidget对象被传递到该页面天生器类,这样会导致1个致命性毛病:
//做1些有用的事情
}
现在,既然你已了解了这个操纵符在PHP5是如何使用的,那末,为了验证被传递到它的"addHTMLElement()"方法的对象的类型,让我们再定义相应的网页天生器类。下面是这个类的新的签名,我在前面已提到,它使用了"instanceof"操纵符:
private$output='';
private$title;
publicfunction__construct($title='DefaultPage'){
$this->title=$title;
}
publicfunctiondoHeader(){
$this->output='<html><head><title>'.$this->title.'</title></head><body>';
}
publicfunctionaddHTMLElement($htmlElement){
if(!$htmlElementinstanceofHTMLElement){
thrownewException('Invalid(X)HTMLelement');
}
$this->output.=$htmlElement->getHTML();
}
publicfunctiondoFooter(){
$this->output.='</body></html>';
}
publicfunctionfetchHTML(){
return$this->output;
}
}
请留意,在上面的类中,为了肯定所有传递的对象是早些时候定义的"HTMLElement"类的实例,"instanceof"操纵符是如何包括在"addHTMLElement()"方法中的。现在,有可能重新构建你前面看到的网页,在这类情况下,请确保所有的传递到该网页天生器类的输进对象都是真实的(X)HTMLwidget对象。下面是相应示例:
//天生1些HTML元素
$h1=newHeader1(array('name'=>'header1','class'=>'headerclass'),'ContentforH1elementgoeshere');
$div=newDiv(array('name'=>'div1','class'=>'divclass'),'ContentforDivelementgoeshere');
$par=newParagraph(array('name'=>'par1','class'=>'parclass'),'ContentforParagraphelementgoeshere');
$teststr='ThisisnotaHTMLelement';
//实例化页面天生器类
$pageGen=newPage天生器();
$pageGen->doHeader();
//添加'HTMLElement'对象
$pageGen->addHTMLElement($teststr)//把简单的字符串传递到这个方法
$pageGen->addHTMLElement($h1);
$pageGen->addHTMLElement($div);
$pageGen->addHTMLElement($par);
$pageGen->doFooter();
//显示网页
echo$pageGen->fetchHTML();
}
catch(Exception$e){
echo$e->getMessage();
exit();
}
正如你在上面的示例已看到的,我把1个简单的测试用字符串(其实不是1个"HTMLElement"对象)传递到该页面天生器类中,这将通过addHTMLElement()"方法抛出1个异常-为特定的"catch"块所捕捉,以下所示:
此时,为了肯定输进对象的有效性,我使用了"instanceof"操纵符,这样以来,可以把上面的网页天生器类转换成1部份更加有效的代码片断。我希看你能真正体会到,通过使用这个操纵符,对你的类的方法的输进进行过滤的极端重要性,这样便可以够免除外来的不正确的数据输进。
在展现了"instanceof"操纵符在网页天生器类内的正确切现后,还有更多的事情要做。类似于我在前面1篇文章中为PHP4所编写的(X)HTMLwidget类,我想包括这个操纵符作为它们的"getHTML()"方法的1部份,这样便可以够答应创建天生嵌套的(X)HTML元素的网页。下面,让我们讨论这是如何实现的。
#p#分页标题#e#
4、扩大"instanceof"操纵符的使用:嵌套(X)HTMLwidget
好。你已看到了"instanceof"操纵符在被直接注进到页面天生器类的输进对象进行类型检查方面所表现出的良好功能。现在,我将再进1步来把1个检查例程添加到(X)HTMLwidget类的构造器和"getHTML()"方法中,这样它们可以接受其它的widget作为输进参数。请检查下面改进的类:
private$output='<div';
private$data;
publicfunction__construct($attributes=array(),$data){
if(!$datainstanceofHTMLElement&&!is_string($data)){
thrownewException('Invalidparametertype');
}
parent::__construct($attributes);
$this->data=$data;
}
//'getHTML()'方法的具体实现
publicfunctiongetHTML(){
foreach($this->attributesas$attribute=>$value){
$this->output.=$attribute.'="'.$value.'"';
}
$this->output=substr_replace($this->output,'>',⑴);
$this->output.=($this->datainstanceofHTMLElement)?
$this->data->getHTML():$this->data;
$this->output.='</div>';
return$this->output;
}
}
classHeader1extendsHTMLElement{
private$output='<h1';
private$data;
publicfunction__construct($attributes=array(),$data){
if(!$datainstanceofHTMLElement&&!is_string($data)){
thrownewException('Invalidparametertype');
}
parent::__construct($attributes);
$this->data=$data;
}
//'getHTML()'方法的具体实现
publicfunctiongetHTML(){
foreach($this->attributesas$attribute=>$value){
$this->output.=$attribute.'="'.$value.'"';
}
$this->output=substr_replace($this->output,'>',⑴);
$this->output.=($this->datainstanceofHTMLElement)?
$this->data->getHTML():$this->data;
$this->output.='</h1>';
return$this->output;
}
}
classParagraphextendsHTMLElement{
private$output='<p';
private$data;
publicfunction__construct($attributes=array(),$data){
if(!$datainstanceofHTMLElement&&!is_string($data)){
thrownewException('Invalidparametertype');
}
parent::__construct($attributes);
$this->data=$data;
}
//'getHTML()'方法的具体实现
publicfunctiongetHTML(){
foreach($this->attributesas$attribute=>$value){
$this->output.=$attribute.'="'.$value.'"';
}
$this->output=substr_replace($this->output,'>',⑴);
$this->output.=($this->datainstanceofHTMLElement)?
$this->data->getHTML():$this->data;
$this->output.='</p>';
return$this->output;
}
}
classUnorderedListextendsHTMLElement{
private$output='<ul';
private$items=array();
publicfunction__construct($attributes=array(),$items=array()){
parent::__construct($attributes);
if(!is_array($items)){
thrownewException('Invalidparameterforlistitems');
}
$this->items=$items;
}
//'getHTML()'方法的具体实现
publicfunctiongetHTML(){
foreach($this->attributesas$attribute=>$value){
$this->output.=$attribute.'="'.$value.'"';
}
$this->output=substr_replace($this->output,'>',⑴);
foreach($this->itemsas$item){
$this->output.=($iteminstanceof
HTMLElement)?'<li>'.$item->getHTML().'</li>':'<li>'.$item.'</li>';
}
$this->output.='</ul>';
return$this->output;
}
}
如上面的类所展现的,为了答应在天生相应的网页时实现嵌套的(X)HTML元素,我分别重构了它们的构造器和"getHTML()"方法。请留意,我在每1个类的构造器中包括了下面的条件块:
thrownewException('Invalidparametertype');
}
至此,我实际做的是确保唯一字符串数据和"HTMLElement"类型对象答应作为每1个类的输进参数。否则,将分别由各自方法抛出1个异常,并且有可能导致利用程序的停止履行。所以,这就是对输进数据的检查进程。现在,让我们看1下"getHTML()"方法的新的签名,其中也使用了"instanceof"操纵符:
>getHTML():$this->data;
如你所见,在这类情况下,对利用(X)HTMLwidget类的多态性特点方面this操纵符是非常有用的。假设$data属性也是1个widget,那末它的"getHTML()"方法将被正确调用,这会导致显示嵌套的网页元素。另1方面,假设它仅是1个字符串,那末它就被直接添加到当前类的所有输出上。
至此,为了确保某些对象属于1个特定的类型,你可能已理解了PHP5中"instanceof"操纵符的用法。正如你在本文中所见,在PHP5中强迫对象类型实在是1个相当直接的工作。现在,你最好开发1个使用这个方法来过滤你的PHP利用程序中的对象的例子来加深自己的理解。
5、小结
在本文中,你学习了如何使用PHP5中的"instanceof"操纵符来检查你的输进对象的类型;但是,我所向你展现的方法不是唯1的。在后面的1篇中,我将向你解释怎样实现PHP5中的良好的"类型提示"特点,这是实现强迫对象类型的另外1种方法。 http://www.fw8.net/
TAG:方法,网页,对象,类型,页面
评论加载中...
|
下一篇: Windows缓存写进失败故障分析