当前位置: 首页 > 图文教程 > 网络编程 > PHP > PHP中实现面向对象编程
$obj=newSomething(6);
构造函数自动赋值5给成员变量x,构造函数和成员函数都是普通的PHP函数,所以你可以使用缺省参数。functionSomething($x="3",$y="5")
然后:$obj=newSomething();//x=3andy=5
$obj=newSomething(8);//x=8andy=5
$obj=newSomething(8,9);//x=8andy=9
缺省参数的定义方法和C++一样,因此你不能传一个值给Y但让X取缺省值,实参的传递是从左到右,当没有更多的实参时函数将使用缺省参数。
只有当继承类的构造函数被调用后,继承类的对象才被创建,父类的构造函数没有被调用,这是PHP不同其他面向对象语言的特点,因为构造函数调用链是面向对象编程的特点。如果你想调用基类的构造函数,你不得不在继承类的构造函数中显式调用它。这样它能工作是因为在继承类中父类的方法全部可用。functionAnother(){
$this->y=5;
$this->Something();//explicitcalltobaseclassconstructor.
}
?>
在面向对象编程中一种好的机制是使用抽象类,抽象类是一种不能实例化而是用来给继承类定义界面的类。设计师经常使用抽象类来强制程序员只能从特定的基类来继承,所以就能确定新类有所需的功能,但在PHP中没有标准的办法做到这一点,不过:
如果你在定义基类是需要这个特点,可以通过在构造函数中调用"die",这样你就可以确保它不能实例化,现在定义抽象类的函数并在每个函数中调用"die",如果在继承类中程序员不想重定义而直接调用基类的函数,将会产生一个错误。
此外,你需要确信因为PHP没有类型,有些对象是从基类继承而来的继承类创建的,因此增加一个方法在基类来辨别类(返回"一些标识")并验证这一点,当你收到一个对象作为参数派上用场。但对于一个恶棍程序没用办法,因为他可以在继承类中重定义此函数,通常这种办法只对懒惰的程序员奏效。当然,最好的办法是防止程序接触到基类的代码只提供界面。
重载在PHP中不被支持。在面向对象编程中你可以通过定义不同参数种类和多少来重载一个同名成员函数。PHP是一种松散的类型语言,所以参数类型重载是没有用的,同样参数个数不同的办法重载也不能工作。
有时候,在面向对象编程中重载构造函数很有用,所以你能以不同的方式创建不同的对象(通过传递不同的参数个数)。一个小巧门可以做到这一点:classMyclass{
functionMyclass(){
$name="Myclass".func_num_args();
$this->$name();
//Notethat$this->$name()isusuallywrongbuthere
//$nameisastringwiththenameofthemethodtocall.
}
functionMyclass1($x){
code;
}
functionMyclass2($x,$y){
code;
}
}
?>
通过这种办法可以部分达到重载的目的。$obj1=newMyclass(1);//WillcallMyclass1
$obj2=newMyclass(1,2);//WillcallMyclass2
上例中,你可以恢复成员变量而没有成员函数(根据文档)。这导致$obj2->x是唯一的方法来存取成员变量(因为没有成员函数)。
这里还有一些方法解决这个问题,但我留下给你因为它会搞脏这个干净的文档。
我希望PHP将来能全面支持串行化。
使用类来操纵保存的数据
PHP和面向对象编程中一个比较好的地方是你很容易定义类来操纵某些东西,并且当需要时调用合适的类。假设有一个HTML文件,你需要通过选择产品的ID号来选择一个产品,你的数据保存在数据库中,而你想显示产品的信息,如价格等等。你有不同种类的产品,同样的动作对不同的产品有不同的含义。
例如,显示一个声音意味着播放它,而对其他产品来说可能是显示一个存储在数据库的图片。你可以用面向对象编程和PHP来达到,代码少但更好。
定义一个类,定义类应该有的方法,然后通过继承来定义每一种产品的类(SoundItem类,ViewableItem类,等等),重定义每个产品类的方法,使它们如你所需。根据你保存在数据库中的表的产品类型字段来给每一种产品类型定义一个类,一个典型的产品表应有字段(id,类型,价格,描述,等等)。
在脚本中你从数据库的表中获取类型信息,然后实例化相应类的对象:$obj=new$type();
$obj->action();
?>
这是PHP比较的特性,你可以调用$obj的显示方法或其他方法而不用去管对象的类型。通过这种技术,当你增加一种新类型的对象时,你不需要去修改脚本。这个方法有点威力,就是定义所有对象应有的方法而不管它的类型,然后在不同的类中以不同的方式来实现,这样就可以在脚本中对不同的类型对象使用他们,再没有if,没有两个程序员在同一个文件里,永远快乐。你相信编程是这样快乐不?维护代价小并且可重用?
如果你带领一组程序员,最好的方法是划分任务,每人可以对某种类和对象负责。国际化可以用同样的技术解决,使合适的类对应使用者选择的不同的语言等等。
复制和克隆
当你创建一个对象$obj,你可以使用$obj2=$obj来拷贝一个对象,新的对象是$obj的一个拷贝(不是引用),所以在赋值完新对象有$obj同新的状态。有时候你不想这样,只想创建和obj同样的新对象,调用新对象的构造函数如同你曾使用过new命令。这可以通过PHP的串行化和使用基类并且其他类必须从基类继承来达到。
进行危险的地带
当你串行化一个对象,你得到一个有特定格式的字符串,如果你有好奇心,可能你会探寻其中的秘密,字符串中有一个东西就是类的名字,你可以解开它:$herring=serialize($obj);
$vec=explode(:,$herring);
$nam=str_replace("\"",\,$vec[2]);
?>
假设你创建一个类"Universe"并且使所有类都从"Universe"继承而来,你可以在"Universe"定义一个克隆的方法:classUniverse{
functionclone(){
$herring=serialize($this);
$vec=explode(:,$herring);
$nam=str_replace("\"",\,$vec[2]);
$ret=new$nam;
return$ret;
}
}
//Then:
$obj=newSomething();
//SomethingextendsUniverse!!
$other=$obj->clone();
?>
你所得的是类Something的新对象如同使用new一样,并且构造函数被调用等等。我不知道这对你是不是有用,这是一个很好的实践,Universe类知道它的继承类的名字。对你来说,唯一的限制是你的想象力!!!
注意:我使用的是PHP4,文章里有些东西可能不适合PHP3。
评论 (0) All