首頁 後端開發 php教程 PHP中实现面向对象编程_PHP

PHP中实现面向对象编程_PHP

Jun 01, 2016 pm 12:33 PM
函數 定義 實現 物件 成員 方法 程式設計 面向

这篇文章介绍在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。

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

手機版龍蛋孵化方法大揭密(一步一步教你如何成功孵化手機版龍蛋) 手機版龍蛋孵化方法大揭密(一步一步教你如何成功孵化手機版龍蛋) May 04, 2024 pm 06:01 PM

手機遊戲成為了人們生活中不可或缺的一部分,隨著科技的發展。它以其可愛的龍蛋形象和有趣的孵化過程吸引了眾多玩家的關注,而其中一款備受矚目的遊戲就是手機版龍蛋。幫助玩家們在遊戲中更好地培養和成長自己的小龍,本文將向大家介紹手機版龍蛋的孵化方法。 1.選擇合適的龍蛋種類玩家需要仔細選擇自己喜歡並且適合自己的龍蛋種類,根據遊戲中提供的不同種類的龍蛋屬性和能力。 2.提升孵化機的等級玩家需要透過完成任務和收集道具來提升孵化機的等級,孵化機的等級決定了孵化速度和孵化成功率。 3.收集孵化所需的資源玩家需要在遊戲中

手機字體大小設定方法(輕鬆調整手機字體大小) 手機字體大小設定方法(輕鬆調整手機字體大小) May 07, 2024 pm 03:34 PM

字體大小的設定成為了重要的個人化需求,隨著手機成為人們日常生活的重要工具。以滿足不同使用者的需求、本文將介紹如何透過簡單的操作,提升手機使用體驗,調整手機字體大小。為什麼需要調整手機字體大小-調整字體大小可以使文字更清晰易讀-適合不同年齡段用戶的閱讀需求-方便視力不佳的用戶使用手機系統自帶字體大小設置功能-如何進入系統設置界面-在在設定介面中找到並進入"顯示"選項-找到"字體大小"選項並進行調整第三方應用調整字體大小-下載並安裝支援字體大小調整的應用程式-開啟應用程式並進入相關設定介面-根據個人

excel函數公式大全 excel函數公式大全 May 07, 2024 pm 12:04 PM

1. SUM函數,用於對一列或一組單元格中的數字進行求和,例如:=SUM(A1:J10)。 2、AVERAGE函數,用於計算一列或一組儲存格中的數字的平均值,例如:=AVERAGE(A1:A10)。 3.COUNT函數,用於計算一列或一組單元格中的數字或文字的數量,例如:=COUNT(A1:A10)4、IF函數,用於根據指定的條件進行邏輯判斷,並返回相應的結果。

如何選擇手機膜,保護你的手機螢幕(選購手機膜的幾個重點與技巧) 如何選擇手機膜,保護你的手機螢幕(選購手機膜的幾個重點與技巧) May 07, 2024 pm 05:55 PM

手機膜成為了必不可少的配件之一,隨著智慧型手機的普及。延長其使用壽命,選擇合適的手機膜可以保護手機螢幕。幫助讀者選出最適合自己的手機膜、本文將介紹選購手機膜的幾個重點與技巧。了解手機膜的材質及類型PET膜,TPU等、手機膜有多種材質,包括強化玻璃。 PET膜較為柔軟、強化玻璃膜具有較好的耐刮花性能,TPU則具有較好的防震性能。可根據個人偏好及需求來決定,在選擇時。考慮螢幕的保護程度不同類型的手機膜對螢幕的保護程度不同。 PET膜則主要起防刮花作用,強化玻璃膜具有較好的耐摔性能。可以選擇具有較好

快速去除老人斑的有效方法(教你簡單又快速消除老人斑的養膚秘訣) 快速去除老人斑的有效方法(教你簡單又快速消除老人斑的養膚秘訣) May 03, 2024 pm 12:01 PM

頸部和手背等暴露部位,老年斑是一種常見的皮膚問題,往往出現在年長者的臉部。也會讓人看起來顯老、它不僅帶給人們的外表困擾。隨著科技的進步和美容技術的發展,現在有了許多簡單而快速的方法來祛除老年斑,然而。恢復年輕又健康的肌膚、幫助您快速消除老年斑、本文將分享一些有效的養膚秘訣。 1.積極保護皮膚免受紫外線傷害的重要性所以避免長時間暴露在陽光下是非常重要的、紫外線是導致老年斑形成的主要原因之一。 2.合理選擇護膚產品,使用含有抗氧化劑和美白成分的產品護膚產品中含有抗氧化劑和美白成分可以幫助減少老年斑的形

Golang 函數接收 map 參數時的注意事項 Golang 函數接收 map 參數時的注意事項 Jun 04, 2024 am 10:31 AM

在Go中傳遞map給函數時,預設會建立副本,對副本的修改不影響原map。如果需要修改原始map,可透過指標傳遞。空map需小心處理,因為技術上是nil指針,傳遞空map給期望非空map的函數會發生錯誤。

使用 Python 解決問題:作為初學者,解鎖強大的解決方案 使用 Python 解決問題:作為初學者,解鎖強大的解決方案 Oct 11, 2024 pm 08:58 PM

Python 讓初學者能夠解決問題。

C++ 程式設計謎題片段:激發思維,提升程式設計水平 C++ 程式設計謎題片段:激發思維,提升程式設計水平 Jun 01, 2024 pm 10:26 PM

C++程式設計謎題涵蓋斐波那契數列、階乘、漢明距離、陣列最大值和最小值等演算法和資料結構概念,透過解決這些謎題,可以鞏固C++知識,提升演算法理解和程式設計技巧。

See all articles