这篇文章介绍在PHP的面向对象编程(OOP)。我将演示如何用面向对象的概念编出较少的代码但更好的程序。祝大家好运。
面向对象编程的概念对每一个作者来说都有不同的看法,我提醒一下一个面向对象语言应有的东西:
- 数据抽象和信息隐藏
- 继承
- 多态性
在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(5);
$see = $obj->getX();
setX 成员函数将 5 赋给对象(而不是类)obj 中成员变量, 然后 getX 返回值 5.
你也可以用对象引用来存取成员变量,例如:$obj->x=6; 然而,这不一种好的面向对象编程的方法。我坚持你应使用成员函数来设置成员变量的值和通过成员函数来读取成员变量。如果你认为成员变量是不可存取的除了使用成员函数的办法,你将成为一个好的面向对象程序员。 但不幸的是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" 的对象拥有父类的所用成员变量及方法函数,再加上自己的成员变量及成员函数。如:
$obj2=new Another;
$obj2->setX(6);
$obj2->setY(7);
多重继承不被支持,所以你不能让一个类继承多个类。
在继承类中你可以重新定义来重定义方法,如果我们在 "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(6);
构造函数自动赋值 5 给成员变量 x, 构造函数和成员函数都是普通的PHP函数,所以你可以使用缺省参数。
function Something($x="3",$y="5")
然后:
$obj=new Something(); // x=3 and y=5
$obj=new Something(8); // x=8 and y=5
$obj=new Something(8,9); // x=8 and y=9
缺省参数的定义方法和 C++ 一样,因此你不能传一个值给 Y 但让 X 取缺省值,实参的传递是从左到右,当没有更多的实参时函数将使用缺省参数。
只有当继承类的构造函数被调用后,继承类的对象才被创建,父类的构造函数没有被调用,这是PHP不同其他面向对象语言的特点,因为构造函数调用链是面向对象编程的特点。如果你想调用基类的构造函数,你不得不在继承类的构造函数中显式调用它。这样它能工作是因为在继承类中父类的方法全部可用。
function Another() {
$this->y=5;
$this->Something(); //explicit call to base class constructor.
}
?>
在面向对象编程中一种好的机制是使用抽象类,抽象类是一种不能实例化而是用来给继承类定义界面的类。设计师经常使用抽象类来强制程序员只能从特定的基类来继承,所以就能确定新类有所需的功能,但在PHP中没有标准的办法做到这一点,不过:
如果你在定义基类是需要这个特点,可以通过在构造函数中调用 "die",这样你就可以确保它不能实例化,现在定义抽象类的函数并在每个函数中调用 "die",如果在继承类中程序员不想重定义而直接调用基类的函数,将会产生一个错误。
此外,你需要确信因为PHP没有类型,有些对象是从基类继承而来的继承类创建的,因此增加一个方法在基类来辨别类(返回 "一些标识")并验证这一点,当你收到一个对象作为参数派上用场。 但对于一个恶棍程序没用办法,因为他可以在继承类中重定义此函数,通常这种办法只对懒惰的程序员奏效。当然,最好的办法是防止程序接触到基类的代码只提供界面。
重载在PHP中不被支持。在面向对象编程中你可以通过定义不同参数种类和多少来重载一个同名成员函数。PHP是一种松散的类型语言,所以参数类型重载是没有用的,同样参数个数不同的办法重载也不能工作。
有时候,在面向对象编程中重载构造函数很有用,所以你能以不同的方式创建不同的对象(通过传递不同的参数个数)。一个小巧门可以做到这一点:
class Myclass {
function Myclass() {
$name="Myclass".func_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 Myclass1($x) {
code;
}
function Myclass2($x,$y) {
code;
}
}
?>
通过这种办法可以部分达到重载的目的。
$obj1=new Myclass(1); //Will call Myclass1
$obj2=new Myclass(1,2); //Will call Myclass2
感觉还不错!
多态性
多态性被定义为当在运行时刻一个对象作为参数传递时,对象能决定调用那个方法的能力。例如,用一个类定义了方法 "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(3,187);
$obj2=new Rectangle(4,5);
$board->niceDrawing($obj); //will call the draw method of Circle.
$board->niceDrawing($obj2); //will call the draw method of Rectangle.
?>
PHP的面向对象编程
纯对象论者认为PHP不是真正的面向对象语言,这是对的。PHP是一种混合语言,你可以用面向对象或传统结构编程的方法来使用它。对于大型工程,然而你可能或需要使用纯面向对象方法来定义类,并在你的工程中只使用对象和类。越来越大的工程通过使用面向对象的方法会获得益处,面向对象工程非常容易维持,容易理解并且重用。这是软件工程的基本。使用这些概念在网站设计中是未来成功的关键。
PHP中的高级面向对象技术
在回顾面向对象的基本概念之后,我将介绍一些更高级的技术。
串行化
PHP并不支持持久性对象,在面向对象语言中持久性对象是一些经过应用程序多次调用仍然保持其状态和功能的对象,这意味着有一种能保存对象到文件或数据库中然后重新装载对象。这种机制称之为串行化。PHP 有一个串行化函数,可以在对象中调用,串行化函数返回一个字符串代表这个对象。然后串行化函数保存的是成员数据而不是成员函数。
在PHP4中,如果你串行化一个对象到字符串 $s, 然后删除此对象,再反串行化对象到 $obj, 你仍然可以调用对象的方法函数。但我不推荐这种方法,这因为(a)这种功能在将来不一定支持(b)这导致一种幻象,如果你保存串行化对象到磁盘并退出程序。将来重新运行此脚本时你不能反串行化此对象并希望对象的方法函数仍有效,因为串行化出来的字符串并没有表示任何成员函数。最后,串行化保存对象的成员变量在PHP中非常有用,仅仅如此. (你可以串行化联合数组和数组到磁盘里)。
例子:
$obj=new Classfoo();
$str=serialize($obj);
// Save $str to disk
//...some months later
//Load str from disk
$obj2=unserialize($str)
?>
上例中,你可以恢复成员变量而没有成员函数(根据文档)。这导致 $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" 定义一个克隆的方法:
class Universe {
function clone() {
$herring=serialize($this);
$vec=explode(:,$herring);
$nam=str_replace("\"",\,$vec[2]);
$ret=new $nam;
return $ret;
}
}
//Then:
$obj=new Something();
//Something extends Universe !!
$other=$obj->clone();
?>
你所得的是类 Something 的新对象如同使用 new 一样,并且构造函数被调用等等。我不知道这对你是不是有用,这是一个很好的实践,Universe 类知道它的继承类的名字。对你来说,唯一的限制是你的想象力!!!
注意:我使用的是PHP4, 文章里有些东西可能不适合PHP3。

计算机编程中常见的if语句是条件判断语句。if语句是一种选择分支结构,它是依据明确的条件选择选择执行路径,而不是严格按照顺序执行,在编程实际运用中要根据程序流程选择适合的分支语句,它是依照条件的结果改变执行的程序;if语句的简单语法“if(条件表达式){// 要执行的代码;}”。

前言本文继续来介绍Python集合模块,这次主要简明扼要的介绍其内的命名元组,即namedtuple的使用。闲话少叙,我们开始——记得点赞、关注和转发哦~ ^_^创建命名元组Python集合中的命名元组类namedTuples为元组中的每个位置赋予意义,并增强代码的可读性和描述性。它们可以在任何使用常规元组的地方使用,且增加了通过名称而不是位置索引方式访问字段的能力。其来自Python内置模块collections。其使用的常规语法方式为:import collections XxNamedT

最近,PHP8.0发布了一个新的邮件库,使得在PHP中发送和接收电子邮件变得更加容易。这个库具有强大的功能,包括构建电子邮件,发送电子邮件,解析电子邮件,获取附件和解决电子邮件获得卡住的问题。在很多项目中,我们都需要使用电子邮件来进行通信和一些必备的业务操作。而PHP8.0中的邮件库可以让我们轻松地实现这一点。接下来,我们将探索这个新的邮件库,并了解如何在我

作为一门高效的编程语言,Go在图像处理领域也有着不错的表现。虽然Go本身的标准库中没有提供专门的图像处理相关的API,但是有一些优秀的第三方库可以供我们使用,比如GoCV、ImageMagick和GraphicsMagick等。本文将重点介绍使用GoCV进行图像处理的方法。GoCV是一个高度依赖于OpenCV的Go语言绑定库,其

随着PHP8.0的发布,DOMDocument作为PHP内置的XML解析库,也有了新的变化和增强。DOMDocument在PHP中的重要性不言而喻,尤其在处理XML文档方面,它的功能十分强大,而且使用起来也十分简单。本文将介绍PHP8.0中DOMDocument的新特性和应用。一、DOMDocument概述DOM(DocumentObjectModel)

Python 中的 main 函数充当程序的执行点,在 Python 编程中定义 main 函数是启动程序执行的必要条件,不过它仅在程序直接运行时才执行,而在作为模块导入时不会执行。要了解有关 Python main 函数的更多信息,我们将从如下几点逐步学习:什么是 Python 函数Python 中 main 函数的功能是什么一个基本的 Python main() 是怎样的Python 执行模式Let’s get started什么是 Python 函数相信很多小伙伴对函数都不陌生了,函数是可

PHP8.0是PHP语言的最新版本,自发布以来已经引发了广泛的关注和争议。其中,最引人瞩目的新特性之一就是Symbol类型。Symbol类型是PHP8.0中新增的一种数据类型,它类似于JavaScript中的Symbol类型,可用于表示独一无二的值。这意味着,两个Symbol类型的值即使完全相同,它们也是不相等的。Symbol类型的使用可以避免在不同的代码段

PHP8.0中的HTTP客户端库PHP8.0的发布带来了很多新特性和改进,其中一个最引人注目的是内置的HTTP客户端库的加入。这个库提供了一个简单的方法来发送HTTP请求并处理返回的响应。在本文中,我们将探讨这个库的主要功能和用法。发送HTTP请求使用PHP8.0内置的HTTP客户端库发送HTTP请求非常简单。在本例中,我们将使用GET方法获取这个网站的首页


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

Dreamweaver Mac版
視覺化網頁開發工具

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。

SublimeText3 Linux新版
SublimeText3 Linux最新版