日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > php >内容正文

php

从零开始攻略PHP(8)——面向对象(下)

發(fā)布時(shí)間:2023/12/10 php 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从零开始攻略PHP(8)——面向对象(下) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

8.編寫代碼類

  每個(gè)分離的函數(shù)可以執(zhí)行一個(gè)明確的任務(wù)。任務(wù)越簡(jiǎn)單,編寫與測(cè)試這個(gè)函數(shù)就越簡(jiǎn)單,當(dāng)然也不要將這個(gè)函數(shù)分得太小——若將程序分成太多的小個(gè)體,讀起來(lái)就會(huì)很困難。

  使用繼承可以重載操作。我們可以替換成一個(gè)大的Display()函數(shù),但是改變整個(gè)頁(yè)面的顯示方式幾乎是不可能的。將顯示功能分成幾個(gè)獨(dú)立的任務(wù)則更好,這樣我們可以只需重載需要改變的部分。

  如下所示的page類提供了簡(jiǎn)單靈活的方法來(lái)創(chuàng)建頁(yè)面:

<?php class Page {// class Page's attributespublic $content; //頁(yè)面的主要內(nèi)容public $title = "TLA Consulting Pty Ltd"; //頁(yè)面的標(biāo)題public $keywords = "TLA Consulting, Three Letter Abbreviation, some of my best friends are search engines"; //metatags便于搜索引擎對(duì)其檢索public $buttons = array("Home" => "home.php", "Contact" => "contact.php", "Services" => "services.php", "Site Map" => "map.php"); //使用一個(gè)數(shù)組來(lái)保存按鈕的文本標(biāo)簽以及該按鈕指向的URL// class Page's operationspublic function __set($name, $value){$this->$name = $value;} //可以從定義訪問(wèn)函數(shù)來(lái)設(shè)置和獲得已定義的變量值開始public function Display(){echo "<html>\n<head>\n";$this -> DisplayTitle();$this -> DisplayKeywords();$this -> DisplayStyles();echo "</head>\n<body>\n";$this -> DisplayHeader();$this -> DisplayMenu($this->buttons);echo $this->content;$this -> DisplayFooter();echo "</body>\n</html>\n";}public function DisplayTitle(){echo "<title>".$this->title."</title>";}public function DisplayKeywords(){echo "<meta name=\"keywords\" content=\"".$this->keywords."\"/>";}public function DisplayStyles(){ ?> <style>h1 {color:white; font-size:24pt; text-align:center; font-family:arial,sans-serif}.menu {color:white; font-size:12pt; text-align:center; font-family:arial,sans-serif; font-weight:bold}td { background:black}p {color:black; font-size:12pt; text-align:justify; font-family:arial,sans-serif}p.foot {color:white; font-size:9pt; text-align:center; font-family:arial,sans-serif; font-weight:bold}a:link,a:visited,a:active {color:white}</style> <?php}public function DisplayHeader(){ ?> <table width="100%" cellpadding="12" cellspacing="0" border="0"><tr bgcolor ="black"><td align ="left"><img src = "logo.gif" /></td><td><h1>TLA Consulting Pty Ltd</h1></td><td align ="right"><img src = "logo.gif" /></td></tr></table> <?php}public function DisplayMenu($buttons){echo "<table width=\"100%\" bgcolor=\"white\" cellpadding=\"4\" cellspacing=\"4\">\n";echo "<tr>\n";//calculate button size$width = 100/count($buttons);while (list($name, $url) = each($buttons)) {$this -> DisplayButton($width, $name, $url, !$this->IsURLCurrentPage($url));}echo "</tr>\n";echo "</table>\n";}public function IsURLCurrentPage($url){if(strpos($_SERVER['PHP_SELF'], $url )==false){return false;}else{return true;}}public function DisplayButton($width,$name,$url,$active = true){if ($active) {echo "<td width = \"".$width."%\"><a href=\"".$url."\"><img src=\"s-logo.gif\" alt=\"".$name."\" border=\"0\" /></a><a href=\"".$url."\"><span class=\"menu\">".$name."</span></a></td>";} else {echo "<td width=\"".$width."%\"><img src=\"side-logo.gif\"><span class=\"menu\">".$name."</span></td>";} }public function DisplayFooter(){ ?> <table width="100%" bgcolor="black" cellpadding="12" border="0"> <tr> <td><p class="foot">&copy; TLA Consulting Pty Ltd.</p><p class="foot">Please see our <a href ="">legal information page</a></p> </td> </tr> </table> <?php} } ?>

  請(qǐng)注意函數(shù)DisplayStyles()、DisplayHeader()和DisplayFooter()需要顯示沒(méi)有經(jīng)過(guò)PHP處理的大量靜態(tài)HTML。因此,我們簡(jiǎn)單地使用了PHP結(jié)束標(biāo)記(?>)、輸入HTML,然后再在函數(shù)體內(nèi)部使用一個(gè)PHP打開標(biāo)記(<?php)。

操作IsURLCurrentPage()將判斷按鈕URL是否指向當(dāng)前頁(yè)。

  這里,我們使用了字符串函數(shù)strpos(),它可以查看給定的URL是否包含在服務(wù)器設(shè)置的變量中。strpos($__SERVER[‘PHP_SELF’], $url)語(yǔ)句將返回一個(gè)數(shù)字(如果$url中的字符串包含在全局變量$_SERVER[‘PHP_SELF’])或者false(如果沒(méi)有包含在全局變量中)。

  首頁(yè)使用page類完成生成頁(yè)面內(nèi)容的大部分工作:

<?phprequire("page.inc");$homepage = new Page();$homepage->content ="<p>Welcome to the home of TLA Consulting.Please take some time to get to know us.</p><p>We specialize in serving your business needsand hope to hear from you soon.</p>";$homepage->Display(); ?>

  在以上的程序清單中可以看出,如果使用Page類,我們?cè)趧?chuàng)建新頁(yè)面的時(shí)候只要做少量工作。通過(guò)這種方法使用類意味著所有頁(yè)面都必須很相似。

  如果希望網(wǎng)站的一些地方使用不同的標(biāo)準(zhǔn)頁(yè),只要將page.inc復(fù)制到名為page2.inc的新文件里,并做一些改變就可以了。這意味著每一次更新或修改page.inc時(shí),要記得對(duì)page2.inc進(jìn)行同樣的修改。

  一個(gè)更好的方法是用繼承來(lái)創(chuàng)建新類,新類從Page類里繼承大多數(shù)功能,但是必須重載需要修改的部分。

  Services頁(yè)面繼承了Page類,但是重載了Display()操作,從而改變了其輸出結(jié)果:

<?phprequire ("page.inc");class ServicesPage extends Page{private $row2buttons = array("Re-engineering" => "reengineering.php","Standards Compliance" => "standards.php","Buzzword Compliance" => "buzzword.php","Mission Statements" => "mission.php");public function Display(){echo "<html>\n<head>\n";$this -> DisplayTitle();$this -> DisplayKeywords();$this -> DisplayStyles();echo "</head>\n<body>\n";$this -> DisplayHeader();$this -> DisplayMenu($this->buttons);$this -> DisplayMenu($this->row2buttons);echo $this->content;$this -> DisplayFooter();echo "</body>\n</html>\n";}}$services = new ServicesPage();$services -> content ="<p>At TLA Consulting, we offer a numberof services. Perhaps the productivity of your employees wouldimprove if we re-engineered your business. Maybe all your businessneeds is a fresh mission statement, or a new batch ofbuzzwords.</p>";$services -> Display(); ?>

  通過(guò)PHP類創(chuàng)建頁(yè)面的好處是顯而易見的,通過(guò)用類完成了大部分工作,在創(chuàng)建頁(yè)面的時(shí)候,我們就可以做更少的工作。在更新頁(yè)面的時(shí)候,只要簡(jiǎn)單地更新類即可。通過(guò)繼承,我們還可從最初的類派生出不同版本的類而不會(huì)破壞這些優(yōu)勢(shì)。

  不過(guò),用腳本創(chuàng)建網(wǎng)頁(yè)要求更多計(jì)算機(jī)處理器的處理操作,應(yīng)該盡量使用靜態(tài)HTML網(wǎng)頁(yè),或者盡可能緩存腳本輸出,從而減少在服務(wù)器上的載入操作。

?

9.PHP面向?qū)ο蟮母呒?jí)功能

  9.1 使用Pre-Class常量

  可以在不需要初始化該類的情況下使用該類中的常量

class Math {const pi = 3.14159; //定義常量 }echo Math::pi;

  可以通過(guò)使用::操作符指定常量所屬的類來(lái)訪問(wèn)Per-Class常量。

  9.2 實(shí)現(xiàn)靜態(tài)方法

  和Pre-Class常量的思想一樣,可以在未初始化類的情況下直接調(diào)用這個(gè)方法,不過(guò),在這個(gè)靜態(tài)方法中,不允許使用?this?關(guān)鍵字,因?yàn)榭赡軙?huì)沒(méi)有可以引用的對(duì)象。

class Math {static function squared($input) {return $input * $input;}}echo Math::squared(8);

  9.3 檢查類的類型和類型提示

  instanceof?關(guān)鍵字允許檢查一個(gè)對(duì)象的類型。可以檢查一個(gè)對(duì)象是否是特定類的實(shí)例,是否是從某個(gè)類繼承過(guò)來(lái)或者是否實(shí)現(xiàn)了某個(gè)接口。

  另外,類型檢查等價(jià)于?instanceof?的作用。

function check_hint(B $someclass){// ... }

  以上示例將要求$someclass必須是類B的實(shí)例。如果按如下方式傳入了類A的一個(gè)實(shí)例:

check_hint($a);

  將產(chǎn)生如下所示的致命錯(cuò)誤:

Fatal error: Argument 1 must be an instance of B

  9.4 延遲靜態(tài)綁定

  PHP 5.3版本引入了延遲靜態(tài)綁定(late static binding)的概念,該特性允許在一個(gè)靜態(tài)繼承的上下文對(duì)一個(gè)被調(diào)用類的引用。父類可以使用子類重載的靜態(tài)方法。如下所示的是PHP手冊(cè)提供的延遲靜態(tài)綁定示例:

<?phpclass A{public static function who(){echo __CLASS__;}public static function test(){static::who(); // Here comes Late Static Bindings }}class B extends A{public static function who(){echo __CLASS__;}}B::test();?>

  通俗的說(shuō),就是B通過(guò)繼承走的A里的test(),然后通過(guò)靜態(tài)延遲走的B里重載的who()。

  無(wú)論類是否被重載,允許在運(yùn)行時(shí)調(diào)用類的引用將為你的類提供更多的功能。

  9.5?克隆對(duì)象

  PHP提供了?clone?關(guān)鍵字,該關(guān)鍵字允許復(fù)制一個(gè)已有的對(duì)象。

$c = clone $b;

  將創(chuàng)建與對(duì)象?$b?具有相同類的副本,而且具有相同的屬性值。

  當(dāng)然,可以自己在類中重新定義?__clone?函數(shù),來(lái)控制克隆的過(guò)程。

  9.6 使用抽象類

  PHP提供了抽象類。這些類不能被實(shí)例化,同樣類方法也沒(méi)有實(shí)現(xiàn),只是提供類方法的聲明,沒(méi)有具體實(shí)現(xiàn)。

abstract operationX($param1, $param2);

  包含抽象方法的任何類自身必須是抽象的。

  抽象方法和抽象類主要用于復(fù)雜的類層次關(guān)系中,該層次關(guān)系需要確保每一個(gè)子類都包含并重載了某些特性的方法,這也可以通過(guò)接口來(lái)實(shí)現(xiàn)。

  9.7 使用__call()重載方法

  在PHP中,__call()方法用來(lái)實(shí)現(xiàn)方法的重載。

<?phpclass overload {public function displayArray($array) {foreach($array as $print) {echo $print;echo "<br />";}}public function displayScalar($scalar) {echo $scalar;echo "<br />";}public function __call($method, $p) {if ($method == "display") {if (is_object($p[0])) {$this->displayObject($p[0]);} else if (is_array($p[0])) {$this->displayArray($p[0]);} else {$this->displayScalar($p[0]);}}}}$ov = new overload;$ov->display(array(1, 2, 3));$ov->display('cat');?>

  __call()方法必須帶有兩個(gè)參數(shù)。第一個(gè)包含了被調(diào)用的方法名稱,而第二個(gè)參數(shù)包含了傳遞給該方法的參數(shù)數(shù)組。

  使用?__call?方法,不需要實(shí)現(xiàn)任何?display()?方法。

  9.8 使用__autoload()方法

  __autoload()函數(shù)將在實(shí)例化一個(gè)還沒(méi)有被聲明的類時(shí)自動(dòng)調(diào)用。

  __autoload()方法的主要用途是嘗試包含或請(qǐng)求任何用來(lái)初始化所需類的文件。

  9.9 實(shí)現(xiàn)迭代器和迭代

  可以使用foreach()方法通過(guò)循環(huán)方式取出一個(gè)對(duì)象的所有屬性,就像數(shù)組方式一樣。

<?phpclass myClass{public $a = "5";public $b = "7";public $c = "9";}$x = new myClass;foreach($x as $attribute){echo $attribute."<br />";}?>

  如果需要一些更加復(fù)雜的行為,可以實(shí)現(xiàn)一個(gè)iterator(迭代器)。要實(shí)現(xiàn)一個(gè)迭代器,必須將要迭代的類實(shí)現(xiàn)IteratorAggregare接口,并且定義一個(gè)能夠返回該迭代類實(shí)例的getIterator方法。這個(gè)類必須實(shí)現(xiàn)Iterator接口,該接口提供了一系列必須實(shí)現(xiàn)的方法。

  迭代器和迭代的示例基類:

?

<?php class ObjectIterator implements Iterator { //迭代器 這個(gè)類實(shí)現(xiàn)了interator接口private $obj;private $count;private $currentIndex;function __construct($obj){$this->obj = $obj;$this->count = count($this->obj->data);}function rewind(){$this->currentIndex = 0;}function valid(){return $this->currentIndex < $this->count;}function key(){return $this->currentIndex;}function current(){return $this->obj->data[$this->currentIndex];}function next(){$this->currentIndex++;} }class Object implements IteratorAggregate //接口 {public $data = array();function __construct($in){$this->data = $in;}function getIterator(){return new ObjectIterator($this); //返回迭代示例的方法 } }$myObject = new Object(array(2, 4, 6, 8, 10));$myIterator = $myObject->getIterator(); for($myIterator->rewind(); $myIterator->valid(); $myIterator->next()) {$key = $myIterator->key();$value = $myIterator->current();echo $key." => ".$value."<br />"; }?>

  ObjectIterator類具有Iterator接口所要求的一系列函數(shù):

    · 構(gòu)造函數(shù)并不是必需的,但是很明顯,它是設(shè)置將要迭代的項(xiàng)數(shù)和當(dāng)前數(shù)據(jù)項(xiàng)鏈接的地方。

    · rewind()函數(shù)將內(nèi)部數(shù)據(jù)指針設(shè)置回?cái)?shù)據(jù)開始處。

    · valid()函數(shù)將判斷數(shù)據(jù)指針的當(dāng)前位置是否還存在更多數(shù)據(jù)。

    · key()函數(shù)將返回?cái)?shù)據(jù)指針的值。

    · value()函數(shù)將返回保存在當(dāng)前數(shù)據(jù)指針的值。

    · next()函數(shù)在數(shù)據(jù)中移動(dòng)數(shù)據(jù)指針的位置。

  像這樣使用Iterator類的原因就是即使?jié)撛诘膶?shí)現(xiàn)發(fā)生了變化,數(shù)據(jù)的接口還是不會(huì)發(fā)生變化。

  9.10 將類轉(zhuǎn)換成字符串

  __toString()函數(shù)的所有返回內(nèi)容都將被echo語(yǔ)句打印。

<?php$p = new Printable;echo $p;class Printable{public $testone;public $testtwo;public function __toString(){return(var_export($this, TRUE));}}?>

  var_export()函數(shù)打印出了類中的所有屬性值。

  9.11 使用Reflection(反射)API

  PHP的面向?qū)ο笠孢€包括反射API。反射是通過(guò)訪問(wèn)已有類和對(duì)象來(lái)找到類和對(duì)象的結(jié)構(gòu)和內(nèi)容的能力。

  顯示關(guān)于Page類的信息:

<?phprequire_once("page.inc");$class = new ReflectionClass("Page");echo "<pre>".$class."</pre>";?>

  這里使用了Reflection類的__toString()方法來(lái)打印這個(gè)數(shù)據(jù)。注意,<pre>標(biāo)記位于不同的行上,不要與__toString()方法混淆。

?

整理自《PHP和MySQL Web開發(fā)》

?

?

?

轉(zhuǎn)載于:https://www.cnblogs.com/xulei1992/p/5806422.html

總結(jié)

以上是生活随笔為你收集整理的从零开始攻略PHP(8)——面向对象(下)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。