面向对象编程的概念对每一个作者来说都有不同的看法我提醒一下一个面向对象语言应有的东西
数据抽象和信息隐藏
继承
多态性
在PHP中使用类进行封装的办法
class Something {
// In OOP classes are usually named starting with a cap letter
var $x;
function setX($v) {
// Methods start in lowercase then use lowercase to seprate
// words in the method name example getValueOfArea()
$this>x=$v;
}
function getX() {
return $this>x;
}
}
?>
当然你可以用你自己的办法但有一个标准总是好的
PHP中类的数据成员使用 var 定义数据成员是没有类型直到被赋值一个数据成员可能是一个 integer数组联合数组(associative array)或甚至对象(object) 方法在类里定义成函数在方法里存取数据成员你必须使用$this>name 这样的办法否则对方法来说是一个函数的局部变量
使用 new 来创建一个对象
$obj = new Something;
然后使用成员函数
$obj>setX();
$see = $obj>getX();
setX 成员函数将 赋给对象(而不是类)obj 中成员变量 然后 getX 返回值
你也可以用对象引用来存取成员变量例如$obj>x=; 然而这不一种好的面向对象编程的方法我坚持你应使用成员函数来设置成员变量的值和通过成员函数来读取成员变量如果你认为成员变量是不可存取的除了使用成员函数的办法你将成为一个好的面向对象程序员 但不幸的是PHP本身没有办法声明一个变量是私有的所以允许糟糕的代码存在
在 PHP 中继承使用 extend 来声明
class Another extends Something {
var $y;
function setY($v) {
// Methods start in lowercase then use lowercase to seperate
// words in the method name example getValueOfArea()
$this>y=$v;
}
function getY() {
return $this>y;
}
}
?>
这样类 Another 的对象拥有父类的所用成员变量及方法函数再加上自己的成员变量及成员函数如
$obj=new Another;
$obj>setX();
$obj>setY();
多重继承不被支持所以你不能让一个类继承多个类
在继承类中你可以重新定义来重定义方法如果我们在 Another 重新定义 getX那么我们不再能存取 Something 中的成员函数 getX 同样如果我们在继承类中声明一个和父类同名的成员变量那么继承类的变量将隐藏父类的同名变量
你可以定义一个类的构造函数 构造函数是和类同名的成员函数在你创建类的对象时被调用
class Something {
var $x;
function Something($y) {
$this>x=$y;
}
function setX($v) {
$this>x=$v;
}
function getX() {
return $this>x;
}
}
?>
所以可以用如下方法创建对象
$obj=new Something();
构造函数自动赋值 给成员变量 x 构造函数和成员函数都是普通的PHP函数所以你可以使用缺省参数
function Something($x=$y=)
然后:
$obj=new Something(); // x= and y=
$obj=new Something(); // x= and y=
$obj=new Something(); // x= and y=
缺省参数的定义方法和 C++ 一样因此你不能传一个值给 Y 但让 X 取缺省值实参的传递是从左到右当没有更多的实参时函数将使用缺省参数
只有当继承类的构造函数被调用后继承类的对象才被创建父类的构造函数没有被调用这是PHP不同其他面向对象语言的特点因为构造函数调用链是面向对象编程的特点如果你想调用基类的构造函数你不得不在继承类的构造函数中显式调用它这样它能工作是因为在继承类中父类的方法全部可用
function Another() {
$this>y=;
$this>Something(); //explicit call to base class constructor
}
?>
在面向对象编程中一种好的机制是使用抽象类抽象类是一种不能实例化而是用来给继承类定义界面的类设计师经常使用抽象类来强制程序员只能从特定的基类来继承所以就能确定新类有所需的功能但在PHP中没有标准的办法做到这一点不过
如果你在定义基类是需要这个特点可以通过在构造函数中调用 die这样你就可以确保它不能实例化现在定义抽象类的函数并在每个函数中调用 die如果在继承类中程序员不想重定义而直接调用基类的函数将会产生一个错误
此外你需要确信因为PHP没有类型有些对象是从基类继承而来的继承类创建的因此增加一个方法在基类来辨别类(返回 一些标识)并验证这一点当你收到一个对象作为参数派上用场 但对于一个恶棍程序没用办法因为他可以在继承类中重定义此函数通常这种办法只对懒惰的程序员奏效当然最好的办法是防止程序接触到基类的代码只提供界面
重载在PHP中不被支持在面向对象编程中你可以通过定义不同参数种类和多少来重载一个同名成员函数PHP是一种松散的类型语言所以参数类型重载是没有用的同样参数个数不同的办法重载也不能工作
有时候在面向对象编程中重载构造函数很有用所以你能以不同的方式创建不同的对象(通过传递不同的参数个数)一个小巧门可以做到这一点
class Myclass {
function Myclass() {
$name=Myclassfunc_num_args();
$this>$name();
//Note that $this>$name() is usually wrong but here
//$name is a string with the name of the method to call
}
function Myclass($x) {
code;
}
function Myclass($x$y) {
code;
}
}
?>
通过这种办法可以部分达到重载的目的
$obj=new Myclass(); //Will call Myclass
$obj=new Myclass(); //Will call Myclass
多态性
多态性被定义为当在运行时刻一个对象作为参数传递时对象能决定调用那个方法的能力例如用一个类定义了方法 draw继承类重定义 draw 的行为来画圆或正方形这样你就有一个参数为 x 的函数在函数里可以调用$x>draw() 如果支持多态性那么 draw 方法的调用就取决于对象 x 的类型多态性在PHP中很自然被支持(想一想这种情况在C++编译器中如果编译那一个方法被调用?然而你不知道对象的类型是什么当然现在不是这种情况)
幸好PHP支持多态性
function niceDrawing($x) {
//Supose this is a method of the class Board
$x>draw();
}
$obj=new Circle();
$obj=new Rectangle();
$board>niceDrawing($obj); //will call the draw method of Circle
$board>niceDrawing($obj); //will call the draw method of Rectangle
?>
PHP的面向对象编程
纯对象论者认为PHP不是真正的面向对象语言这是对的PHP是一种混合语言你可以用面向对象或传统结构编程的方法来使用它对于大型工程然而你可能或需要使用纯面向对象方法来定义类并在你的工程中只使用对象和类越来越大的工程通过使用面向对象的方法会获得益处面向对象工程非常容易维持容易理解并且重用这是软件工程的基本使用这些概念在网站设计中是未来成功的关键
PHP中的高级面向对象技术
在回顾面向对象的基本概念之后我将介绍一些更高级的技术
串行化
PHP并不支持持久性对象在面向对象语言中持久性对象是一些经过应用程序多次调用仍然保持其状态和功能的对象这意味着有一种能保存对象到文件或数据库中然后重新装载对象这种机制称之为串行化PHP 有一个串行化函数可以在对象中调用串行化函数返回一个字符串代表这个对象然后串行化函数保存的是成员数据而不是成员函数
在PHP中如果你串行化一个对象到字符串 $s 然后删除此对象再反串行化对象到 $obj 你仍然可以调用对象的方法函数但我不推荐这种方法这因为(a)这种功能在将来不一定支持(b)这导致一种幻象如果你保存串行化对象到磁盘并退出程序将来重新运行此脚本时你不能反串行化此对象并希望对象的方法函数仍有效因为串行化出来的字符串并没有表示任何成员函数最后串行化保存对象的成员变量在PHP中非常有用仅仅如此 (你可以串行化联合数组和数组到磁盘里)
例子:
$obj=new Classfoo();
$str=serialize($obj);
// Save $str to disk
//some months later
//Load str from disk
$obj=unserialize($str)
?>
上例中你可以恢复成员变量而没有成员函数(根据文档)这导致 $obj>x 是