我們可以想象我們的宇宙是由不同的對象組成,像太陽,地球,月亮等等。同樣我們可以想象我們的車由不同的組件組成如車輪,轉(zhuǎn)向盤,齒輪等。同樣有面向?qū)ο缶幊谈拍?,假設(shè)一切作為對象使用不同的對象實例化一個事物。
面向?qū)ο蟮母拍?/h2>
在我們進入講述細節(jié)之前,讓我們首先定義面向?qū)ο缶幊滔嚓P(guān)的重要術(shù)語。
類:這是一個編程定義的數(shù)據(jù)類型,包括本地的方法以及本地數(shù)據(jù)。你能想到的一個類模板制作許多相同類型的實例(或類)的對象。
對象:一個單獨的數(shù)據(jù)結(jié)構(gòu)用來定義的一個類的實例。你定義一個類,然后讓許多對象屬于它。對象也被稱為實例。
成員變量:這是在類的內(nèi)部定義的變量。這些數(shù)據(jù)對于外部類是不可見的,但是可以通過成員函數(shù)來訪問。對象一旦創(chuàng)建這些變量被稱該對象的屬性。
成員函數(shù):這些函數(shù)定義在一個類,用于訪問對象的數(shù)據(jù)。
繼承:當一個類被定義為繼承一個已經(jīng)存在的父類,我們稱這個類為繼承類,這里繼承類可以使用父類的一些成員函數(shù)和變量。
父類:一個類被另一個類繼承。這個類也被稱為基類或超類。
子類:一個類繼承另一個類。這個類也被稱為一個子類或派生類
多態(tài)性:這是一個面向?qū)ο蟮母拍?,相同的函?shù)可以用于不同的目的。例如函數(shù)名仍將是相同的,但它采取不同的數(shù)量的參數(shù),可以做不同的任務(wù),完成不同的工作。
重載:一種多態(tài)性的部分指在所有的運算符有不同的實現(xiàn)取決于他們的類型參數(shù)。同樣的函數(shù)也可以重載伴隨著不同的實現(xiàn)。
數(shù)據(jù)抽象:任何表示的數(shù)據(jù)的實現(xiàn)細節(jié)是隱藏(抽象)。
封裝:是指一個概念,我們的所有數(shù)據(jù)和成員函數(shù)封裝在一起,形成一個對象
構(gòu)造函數(shù):指一個特殊的函數(shù)類型可以被自動調(diào)用,構(gòu)造函數(shù)的類會在每次創(chuàng)建新對象時先調(diào)用此方法。
析構(gòu)函數(shù):指一個特殊的函數(shù)類型可以被自動調(diào)用,會在到某個對象的所有引用都被刪除或者當對象被顯式銷毀時執(zhí)行。
定義的 PHP 類
在 PHP 中定義一個新類的一般形式如下:
<?php class phpClass{ var $var1; var $var2 = "constant string"; function myfunc ($arg1, $arg2) { [..] } [..] } ?>
這是每一行的描述:
定義類形式 Class,后面是您想要定義的類的名稱。
一組花括號包含任意數(shù)量的變量聲明和函數(shù)定義。
變量聲明開始使用 var 的特殊形式,緊隨其后的是一個傳統(tǒng)的 $ 變量名;他們可能也有一個初始化分配一個常量值。
函數(shù)定義看起來很像獨立的 PHP 函數(shù),但該類和將被用于設(shè)置和訪問對象數(shù)據(jù)。
例子
這里是一個例子定義了一個書籍類型類:
<?php class Books{ /* Member variables */ var $price; var $title; /* Member functions */ function setPrice($par){ $this->price = $par; } function getPrice(){ echo $this->price ."<br/>"; } function setTitle($par){ $this->title = $par; } function getTitle(){ echo $this->title ." <br/>"; } } ?>
變量 $this 是一個特殊的變量,它指的是同一個對象,本身。
用 PHP 創(chuàng)建對象
你一旦定義好你的類,那么您可以創(chuàng)建許多對象。下面是一個例子,如何使用 new 操作符創(chuàng)建對象。
$physics = new Books; $maths = new Books; $chemistry = new Books;
在這里,我們已經(jīng)創(chuàng)建了三個對象,這些對象是相互獨立的,他們有自己的單獨存在的空間。接下來,我們將看到如何訪問成員函數(shù)和成員變量的過程。
調(diào)用成員函數(shù)
創(chuàng)建對象后,您將能夠使用相關(guān)的對象調(diào)用成員函數(shù)。一個成員函數(shù)將能夠處理相關(guān)對象的成員變量。
下面的例子顯示了如何通過調(diào)用成員函數(shù)設(shè)置標題和價格三本書。
$physics->setTitle( "Physics for High School" ); $chemistry->setTitle( "Advanced Chemistry" ); $maths->setTitle( "Algebra" ); $physics->setPrice( 10 ); $chemistry->setPrice( 15 ); $maths->setPrice( 7 );
現(xiàn)在你調(diào)用另一個成員函數(shù)獲取設(shè)置在上面的例子的值:
$physics->getTitle(); $chemistry->getTitle(); $maths->getTitle(); $physics->getPrice(); $chemistry->getPrice(); $maths->getPrice();
這將會產(chǎn)生以下結(jié)果:
Physics for High School Advanced Chemistry Algebra 10 15 7
構(gòu)造函數(shù)
構(gòu)造函數(shù)是特殊類型的函數(shù)自動創(chuàng)建一個對象時函數(shù)的功能會自動執(zhí)行。所以我們充分利用這個行為,通過構(gòu)造函數(shù)初始化很多功能。PHP 提供了一個特殊的函數(shù)叫做 __construct()
來定義一個構(gòu)造函數(shù)。你可以把參數(shù)傳遞到構(gòu)造函數(shù)中。以下示例將為書籍類,在創(chuàng)建對象的時候它將創(chuàng)建一個構(gòu)造函數(shù)用來初始化價格和標題這本書。
function __construct( $par1, $par2 ){ $this->price = $par1; $this->title = $par2; }
現(xiàn)在我們不需要調(diào)用設(shè)置好的函數(shù)分別設(shè)置價格和標題。我們可以初始化這兩個成員變量只在創(chuàng)建對象的時候。檢查以下例子:
$physics = new Books( "Physics for High School", 10 ); $maths = new Books ( "Advanced Chemistry", 15 ); $chemistry = new Books ("Algebra", 7 ); /* Get those set values */ $physics->getTitle(); $chemistry->getTitle(); $maths->getTitle(); $physics->getPrice(); $chemistry->getPrice(); $maths->getPrice();
這將產(chǎn)生以下結(jié)果:
Physics for High School Advanced Chemistry Algebra 10 15 7
析構(gòu)函數(shù)
您可以定義析構(gòu)函數(shù):就像定義一個構(gòu)造函數(shù),析構(gòu)函數(shù)使用函數(shù)__destruct()
。你可以調(diào)用一個析構(gòu)函數(shù)釋放所有資源。
繼承
PHP 類定義可以使用 extends 關(guān)鍵字繼承一個父類。語法如下:
class Child extends Parent { <definition body> }
繼承的影響是子類 (或派生類或子類)具有以下特點:
自動繼承所有父類的成員變量聲明。
自動繼承父類的成員函數(shù)。(默認情況下)像父類一樣使用函數(shù)。以下例子書類繼承和基于需求增加了更多的功能。
class Novel extends Books{ var publisher; function setPublisher($par){ $this->publisher = $par; } function getPublisher(){ echo $this->publisher. "<br />"; } }
現(xiàn)在除了繼承功能,類帶了兩個額外的成員函數(shù)。
函數(shù)重載
函數(shù)定義子類覆蓋與父類中相同的屬性及方法名稱。在子類中,我們可以修改繼承自父類中的方法。
在以下示例中 getPrice 和 getTitle 方法重載。
function getPrice(){ echo $this->price . "<br/>"; return $this->price; } function getTitle(){ echo $this->title . "<br/>"; return $this->title; }
公共成員
除非你指定,否則類的屬性和方法默認都是公共的。也就是說,他們可能在三種可能的情況下被訪問:
從類外聲明。
在類中聲明。
從另一個類中實現(xiàn)的類聲明它。
直到現(xiàn)在我們看到所有成員都作為公共成員。如果你想限制類的成員的可訪問性,然后你必須定義類成員為 private 或者 protected。
私有成員
通過指定一個私有成員,你可以限制其訪問對象在類外訪問它。類的私有成員不能在繼承類中調(diào)用它,也不能從類外部訪問。
私有屬性或方法只能在本類內(nèi)使用:
class MyClass { private $car = "skoda"; $driver = "SRK"; function __construct($par) { // Statements here run every time // an instance of the class // is created. } function myPublicFunction() { return("I'm visible!"); } private function myPrivateFunction() { return("I'm not visible outside!"); } }
當 MyClass 類被一個類使用關(guān)鍵字 extends 繼承時,myPublicFunction() 方法在子類中是可用的,屬性$drive也一樣。方法 myPrivateFunction() 和屬性 $car 在子類中是不可以被繼承的當然也不可以用,因為他們被聲明為了私有的。
受保護成員
訪問一個受保護的屬性或方法并在類中聲明它,以及使用關(guān)鍵字 extends 繼承該類時。保護成員在兩種類型的類之外無法使用。一個類成員可以使用關(guān)鍵字 protected 在其前面。
這是不同版本的 MyClass 類:
class MyClass { protected $car = "skoda"; $driver = "SRK"; function __construct($par) { // Statements here run every time // an instance of the class // is created. } function myPublicFunction() { return("I'm visible!"); } protected function myPrivateFunction() { return("I'm visible in child class!"); } }
接口
接口被開發(fā)人員定義為提供一個普通的方法名。不同的開發(fā)人員可以根據(jù)他們不同的需求來分別實現(xiàn)這些接口。你可以說,接口是根據(jù)不同的需求被開發(fā)人員所實現(xiàn)。
PHP5,可以定義一個接口,如下:
interface Mail { public function sendMail(); }
然后,另一個類像這樣實現(xiàn)該接口:
class Report implements Mail { // sendMail() Definition goes here }
常量
一個常量有點像一個變量,它擁有一個值,但實際上更像一個函數(shù),因為常量是永遠不變的。一旦你聲明一個常量,它不能被改變。
聲明一個常量是很容易的,就像下面這個版本的 MyClass,它完成了常量的定義:
class MyClass { const requiredMargin = 1.7; function __construct($incomingValue) { // Statements here run every time // an instance of the class // is created. } }
在這個類中,requiredMargin 是一個常量。它是用關(guān)鍵字 const 聲明常量,在任何情況不可以改變他的值 1.7。注意,常量的定義沒有 $ 符號,不能像變量那樣。
抽象類
抽象類不能被實例化,只能被繼承。你用關(guān)鍵字 abstract 聲明一個抽象類,就像這樣:
當繼承一個抽象類的時候,子類必須實現(xiàn)抽象類中的所有的抽象方法,另外,這些方法的可見性必須和抽象類中一樣(或更輕松)。
abstract class MyAbstractClass { abstract function myAbstractFunction() { } }
注意,方法定義在一個抽象類中在方法名稱前面之前必須使用關(guān)鍵字 abstract。抽象方法定義在一個非抽象類中是不合法的。
Static關(guān)鍵字
聲明類屬性或方法為靜態(tài),就可以不實例化類而直接訪問。靜態(tài)屬性不能通過一個類已實例化的對象來訪問(但靜態(tài)方法可以)。
試運行下面的例子:
<?php class Foo { public static $my_static = 'foo'; public function staticValue() { return self::$my_static; } } print Foo::$my_static . "\n"; $foo = new Foo(); print $foo->staticValue() . "\n";
final 關(guān)鍵字
PHP 5 介紹了這個 final 關(guān)鍵字。如果父類中的方法被聲明為 final,則子類無法覆蓋該方法。如果一個類被聲明為 final,則不能被繼承。
以下的例子會產(chǎn)生一個致命錯誤:Cannot override final method BaseClass::moreTesting()。
<?php class BaseClass { public function test() { echo "BaseClass::test() called<br>"; } final public function moreTesting() { echo "BaseClass::moreTesting() called<br>"; } } class ChildClass extends BaseClass { public function moreTesting() { echo "ChildClass::moreTesting() called<br>"; } } ?>
調(diào)用父類的構(gòu)造函數(shù)
當子類需要一個構(gòu)造函數(shù)時,需要調(diào)用父類的構(gòu)造函數(shù)而不是在子類中寫一個全新的構(gòu)造函數(shù),我們需要調(diào)用父類的構(gòu)造函數(shù)加一下我們要寫的內(nèi)容,另外在子類的構(gòu)造函數(shù)中做一些初始化是必要的。這是一個簡單的例子:
class Name { var $_firstName; var $_lastName; function Name($first_name, $last_name) { $this->_firstName = $first_name; $this->_lastName = $last_name; } function toString() { return($this->_lastName .", " .$this->_firstName); } } class NameSub1 extends Name { var $_middleInitial; function NameSub1($first_name, $middle_initial, $last_name) { Name::Name($first_name, $last_name); $this->_middleInitial = $middle_initial; } function toString() { return(Name::toString() . " " . $this->_middleInitial); } }
在上面這個例子中,我們有一個父類(Name),它里面有一個二個參數(shù)的構(gòu)造函數(shù),在子類中(NameSub1)有一個帶有 3 個參數(shù)的構(gòu)造函數(shù)。子類 NameSub1 中的構(gòu)造函數(shù)通過調(diào)用其父類中的構(gòu)造函數(shù) Name::Name
(傳遞兩個參數(shù))加以使用,然后增加一個額外的屬性。同樣,NameSub1 定義了 toString() 方法然后重寫父類中的 toString() 方法。
注:上例中定義的,可以在子類中定義和父類中相同的構(gòu)造函數(shù),并且名字名稱相同。