程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> PHP 面向對象詳解

PHP 面向對象詳解

編輯:關於PHP編程

對象的主要三個特性
對象的行為:可以對 對象施加那些操作,開燈,關燈就是行為。
對象的形態:當施加那些方法是對象如何響應,顏色,尺寸,外型。
對象的表示:對象的表示就相當於身份證,具體區分在相同的行為與狀態下有什麼不同。

面向對象模型

面向對象的概念:
oop(面向對象的編程)它能是其代碼更加簡潔易於維護並且具有更強的可重性

什麼是類:
類是具有相同屬性和服務的一組對象的集合比如說人,書,輪船,車都屬於類,他為屬於該類的對象做了一個統一的抽象描述,在編程的語言中類是一個單獨的程序,它應該有一個類名包括屬性的說明和服務兩個部分。
什麼是對象:
對象是系統中描述客觀事件的一個實體,他是構成系統的一個基本單位。*數據與代碼都被捆綁在一個實體當中*,一個對象由一組屬性和對這組屬性進行操作的一組行為組成。
從抽象的角度來說,對象是問題域或實現域中某些事物的一個抽象。他反映該事物在系統中保存的信息和發揮的作用:它是一組屬性和有權對這些屬性進行操作的一個封裝體。客觀世界是由對象和對象之間的聯系組成的。
類和對象的關系:
類與對象的關系就如模具和鑄件的關系,類的實力化的結果就是對象,而對對象的抽象就是類,類描述了一組有相同特性(屬性)和相同行為的對象。

類與屬性和方法

PHP中定義類語法格式:
復制代碼 代碼如下:
class classname [可選屬性]{
public $property [=value];… //用public聲明一個公共標識 然後給予一個變量 變量也可以賦值
function functionname ( args ){ //類的方法裡的成員函數
代碼} …
//類的方法(成員函數)
}

生成對象(類的實例化): $對象名=new classname( );

使用對象的屬性

在一個類中,可以訪問一個特殊指針$this當在該類中通過一個操作設置或訪問該變量時,使用$this->name來引用.
對象的生成
定義好類後用一個new來聲明,由於對象資料的封裝特性,對象是無法由主程序區塊直接訪問的須通過對象來調用類中所定義的屬性和行為函數,間接地達成存取控制類中資料的目的。
對象和類的關系
對象和類的關系:
對象是實際存在的,占有動態資源。
類是對象的藍圖,可能占有靜態資源。
對象屬性占有動態資源
類(靜態)屬性實際上是有類名字空間上的"全局變量"
性能考慮:
每個對象要單獨占用數據空間
增加的調用層次可能消耗執行時間
方法的參數形式和傳遞方式
方法的參數可以是基本數據類型、數組和類對象。
基本數據類型:值參傳遞
數組:值參傳遞
類對象:引用傳遞
構造函數
構造函數是在類中起到初始化的作用
構造函數的生成方法與其他函數一樣只是其名稱必須是__construct().
語法格式:
function __construct(參數){
。。。。。。。。
}
范例:
復制代碼 代碼如下:
class Person{
public $name;
public $sex;
public $age;
function __construct($name,$sex,$age){
echo "我是構造函數<br>";
$this->name=$name;
$this->sex=$sex;
$this->age=$age;
}

輸出結果:初始化

析構函數

當對象脫離其作用域時(例如對象所在的函數已調用完畢),系統自動執行析構函數。應在退出前在析構函數中用釋放內存。
析構函數__destruct 析構函數沒有任何參數
范例:
復制代碼 代碼如下:
class person{
function _ _destruct( )
{ echo "bye bye !"; }
}
$a=new person();

訪問類型
public 公共的(公共修飾符) 類內部與類外部都可以訪問的
private 私有的(私有修飾符) 只能在類內部訪問
protected 受保護的(保護成員修飾符) 子類可以訪問 類外部不可以訪問

oop的三個重要特性

封裝,繼承,多態
封裝性:封裝性就是把對象的屬性和行為結合成一個獨立的單位。
封裝一個類需要兩步 第一步是私有化一個類 第二步是用set和get 做出讀取賦值的操作
他的好處是:隱藏類的實現細節,可以方便加入邏輯控制性,限制對屬性的不合理操作,便於修改增強代碼的可維護性。

__get與__set
一般說把類私有話更符合現實的邏輯。
預定義兩種函數來進行獲取與敷值操作。
__get 獲取值通常是域的值
__set 設置值通常是域的值
__call 調用一個對象中不存在的方法時,就會產生錯誤call()這個方法來處理這種情況。

靜態屬性和方法

static關鍵字 來聲明靜態方法
static靜態變量 在類的內部生成一個靜態變量 就是能夠被所有類的實力化共想 也就是說靜態成員則放到了"初始化靜態段",在類第一次被加載的時候放入的,可以讓堆內存裡面的每個對象所共享
使用方法:self::$靜態屬性、self::靜態方法
static function p(){
echo self::$country;
echo self::PI;//訪問常量
//echo $this->name;在靜態方法中只能操作靜態屬性
//self::p();
}
外部調用:類::$靜態屬性、類::靜態方法

const關鍵字:用來生成常量 常量是唯一的不能改變的 慣例常量為大寫
const CONSTANT = 'constant value'; 生成一個常量
echo self::CONSTANT;//類內部訪問
echo ClassName::CONSTANT;//類外部訪問

繼承性

B類的對象擁有A類的全部屬性與行為,稱作B對A類的繼承。
假如一個類從多個類中繼承了屬性與服務,這稱為多繼承,通常我們成為繼承類為子類被繼承類為父類,在PHP中只有單繼承,但一個父類可以被多個類繼承,但是一個子類只能有一個父類,但是允許關聯繼承,通過繼承可以減化類的定義。
extende聲明繼承關系
語法格式:class B extends A 此范例指明 B繼承了A
類的外部訪問對子類是有效的
子類與父類的屬性與方法
子類繼承父類的所有內容,但父類中的private部分不能直接訪問
子類中新增加的屬性和方法是對父類的擴展
子類中定義的與父類同名的屬性是對父類屬性的覆蓋,同名的方法也是對父類方法的覆蓋

重寫的方法

在子類中,使用parent訪問父類中的被覆蓋的屬性和方法

parent::__construce();
parent::$name;
parent::fun();

覆蓋父類原有屬性
clone克窿對象 語法格式$c=clone $p; $c克窿的對象$p 輸出echo $c->name;

對象比較
===兩個比較運算符。
==是比較兩個對象的內容。
===是比較對象的句柄,即引用地址。

instanceof操作符用於檢測對象實力是否屬於某一個類的類型 屬於返回true 不屬於返回false
__clone()如果想在克隆後改變原對象的內容,需要在__clone()中重寫原本的屬性和方法
function __clone(){
$this->name="我是一個克隆人";
}

final表示一個類是最終版本 也就是說它不能在被子類調用

多態性

多態性是指在父類中定義的屬性或行為被子類繼承之後,可以具有不同的數據類型或表現出不同的行為。這使得同一個屬性或行為在父類及其各個子類中具有不同的語義。
就是說同一種方法在子類與父類中執行的結果不同。
復制代碼 代碼如下:
class A {
function info(){
echo "A INFO";
}
}
class B extends A {
function info(){
echo "B INFO";
}
}
class C extends A {
function info(){
echo "C INFO";
}
}
function printinfo($obj){
function printinfo(A $obj){
if($obj instanceof A)
$obj->info();
$obj->info();
}
}
$a=new A(); $b=new B(); $c=new C();
printinfo($a); //輸出A INFO
printinfo($b); //輸出B INFO
printinfo($c); //輸出C INFO


抽象方法和抽象類

抽象方法是作為子類摸版使用的。
復制代碼 代碼如下:
abstract class Person{
public $name;
abstract function getInfo();
}

抽象類不能被實力話,一個抽象類中,必須有一個抽象方法。但是抽象類中可以定義動態函數。
接口
當一個類繼承了一個接口之後,它要覆蓋接口的所有方法,接口只能聲明常量,接口的方法必須定義為共有否則無法繼承,接口可以與多個接口間繼承
語法:
復制代碼 代碼如下:
interface PCI{
const TYPE="PCI";
//public $name; error
function start();
function stop();
}

接口中的方法可以聲明為static
復制代碼 代碼如下:
interface A{ function a();}
interface B{ function b();}
interface C extends A{ function c();}
class D implements B,C{
function a(){}
function b(){}
function c(){}
}


類的聲明:
復制代碼 代碼如下:
<?php
    權限修飾符 class 類名{ //權限修士符號:public,protected,private 或者省略3者.
      //類體;        //class 是建類關鍵字
    }             //類名必須跟在class 後面,且跟上{}.{}之間放類的成員.
  ?>
//ps:在class關鍵字前可以加權限修飾符外,還可以加static,abstract等關鍵字.一個類,即一對大括號之間的全部內容都要在一段代碼段中,不允許將類中的內容分割成對塊.
<?php
  class ConnDB{
    //....
?>
<?
    //...
  };
?>

成員屬性:
  在類中直接聲明的變量稱為成員屬性/變量.其類型可以為php中的標量類型和復合類型,使用資源類型和空類型是無效的.
此外,成員屬性的聲明時,必須要有關鍵字來修飾:有特定意義的關鍵字:public,protected,private ;不需要特定意義:var.聲明成員屬性時,沒有必要賦初始值.

成員常量:

  以const常量修飾,例如:const PI = 3.1415926;
  常量的輸出不需要實例化,直接由類名+常量名調用即可,格式為: 類名::常量名
ps. 特殊的訪問方法:--------"$this" 和 "::"
1) $"this" 存在於每個成員方法當中,它是一個特殊的對象以用方法.成員方法屬於那個對象,$this應用就代表那個對象,其作用就是專門完成對象內部成員之間的訪問.
2) "::"成為作用域操作符,使用這個操作符可以在不創建對象的情況下調用類中的常量,變量和方法. 其語法格式如下:

  關鍵字::變量名/常量名/方法名

  關鍵字:parent,可以調用父類成員中的成員變量,成員方法和常量;
      self,可以調用當前類中的靜態成員和常量;
      類名,可以調用類中的常量,變量和方法;   
  
成員方法:

  在類中聲明的函數成為成員方法,在一個類中可以聲明多個函數,即對象可以擁有多個成員方法.成員方法的聲明和函數的聲明相同,唯一特殊之處就是成員方法可以有關鍵字對它進行修飾,從而控制其訪問權限.
類的實例化

  創建對象:

    $變量名 = new 類名稱([參數]); //類的實例化.
  訪問類成員:
    $變量名 -> 成員屬性 = 值;
構造方法和析構方法
構造方法是對象創建完成後第一個呗對象自動調用的方法.它存在每個類的聲明當中,是一個特殊的成員方法,一般用來完成一些初始化操作.如果類中沒有構造方法,系統會默認自動生成一個沒有參數的構造方法.
  格式:
復制代碼 代碼如下:
function _construct(形參列表){
      //方法體
    };

析構方法則如構造方法相反,它是在對象被銷毀前最後一個調用的方法.它將完成一個特定的操作,如關閉文件和釋放內存.
  格式:
復制代碼 代碼如下:
function _destruct(){
      //方法體 
    };

面向對象特點:封裝性,抽象性,多態性.
封裝:
  將類中的成員屬性和方法結合成一個獨立的相同單位,並且盡可能的隱藏對象的內容細節.其目的是確保類以外的部分不能隨意存取類的內部數據(成員屬性和成員方法),從而避免外部錯誤對內部數據的影響.
  類的封裝是通過關鍵字public,private,protected,static和final實現的.各關鍵字的作用請查看php相關文檔.
繼承性:
  使一個類繼承並擁有另一個已存在的類的成員屬性和成員方法,其中被繼承的類成為父類,繼承的類成為子類.通過繼承能夠提高代碼的重用性和可維護性.類的繼承用 extends 關鍵字.
  格式:
復制代碼 代碼如下:
class 子類名稱 extends 父類名稱{
      //子類方法體.
    }

通過parent::關鍵字也可以在子類方法中調用父類的成員方法,格式如下:
  parent::父類的成員方法(參數);

覆蓋父類的方法:

  所謂的覆蓋父類的方法,也就是使用子類中的方法替換從父類中繼承的方法,也叫方法的重寫.重寫的關鍵就在與子類中創建與父類中相同的方法,g包括方法名稱,參數和返回類型.

多態性:
  多態性是指一段程序能夠處理多種類型對象的能力.php多態有兩種實現方法,即通過繼承實現多態和通過接口實現多態.
通過繼承實現多態,即通過重寫繼承的成員方法來達到多態的效果.
復制代碼 代碼如下:

<?php
abstract class ParentClass{
abstract function printMessage();
}
class SubClassA extends ParentClass{
function printMessage(){
echo "i am message from class A";
}
}
class SubClassB extends ParentClass{
function printMessage(){
echo "i am message from class B";
}
}
function printMSG($object){
if( $object instanceof ParentClass){
$object->printMessage();
}else{
echo "error!";
}
}
$objectA=new SubClassA();
printMSG($objectA);
$objectB=new SubClassB();
printMSG($objectB);
?>

通過接口實現多態,通過定義接口,與空方法.然後類繼承接口.
復制代碼 代碼如下:

<?php
interface interfaceInfo{
function printMessage();
}
class ClassA implements interfaceInfo{
function printMessage(){
echo "message form class A";
}
}
class ClassB implements interfaceInfo{
function printMessage(){
echo "message form class B";
}
}
function printMSG($object){
if($object instanceof interfaceInfo){
$object -> printMessage();
}else{
echo "error !";
}
}
$objectA =new ClassA();
printMSG($objectA);
$objectB =new ClassB();
printMSG($objectB);
?>

ps. 抽象類和接口.
抽象類和接口都是不能被實例化的特殊類.他們都是能夠配合面向對象多態性一起使用.
抽象類:
  抽象類是一種不能實例化的類,只能作為其他類的父類來使用.抽象類使用abstract 關鍵字來聲明,其格式如下:
復制代碼 代碼如下:
abstract class 抽象類名{
      abstract function 成員方法(參數);//
    }

抽象類和普通類相似,包含成員變量,成員方法.兩者區別在於抽象類至少要包含一個抽象方法.抽象方法沒有方法體,其功能的實現只能在子類中完成.抽象方法也使用關鍵字 abstract 來修飾.

接口:
  繼承特性簡化了對象和類的創建,增強了代碼的可重用性.但php只支持單繼承,如果想實現多重繼承,就要使用接口.
接口的聲明:通過interface 關鍵字來實現,接口中聲明的方法必須是抽象方法,接口中不能聲明變量,只能使用const 關鍵字聲明為常量的成員屬性,並且接口中所有成員都必須具備puclic 的訪問權限.ainterface 聲明接口格式如下:
復制代碼 代碼如下:
inerface 接口名稱{
   //常量成員;//成員只能是常量.
   //抽象方法;
  }

由於接口不能實現實例化操作,因此只能借助子類繼承接口的形式來實現.實現的格式是:
復制代碼 代碼如下:
Class 子類名 implements 接口名1[,接口名2,接口名3,.....]{
  //子類方法體.
}

常用關鍵字:
  1) final:final之意為最終的,最後的.這就以為著通過final 關鍵字修飾的類和方法都為最終版本.不能被繼承,也不能有子類.不能重寫,也不能被覆蓋.
  2) static: 通過static 關鍵字修飾的成員屬性和成員方法稱為靜態屬性和靜態方法.靜態成員屬性和方法不需要被實例化就能直接使用.
   靜態屬性:它屬於類本身,而不屬於類的任何實例.它相當於存儲在類中的全局變量,可以在任何位置通過類來訪問.訪問格式為:
      類名稱::$靜態屬性名稱;
      如果你要在類內部的成員方法中訪問靜態屬性,那麼在靜態屬性的名稱前加上操作符: "self::" 即可.
   靜態方法:由於其不受任何對象限制,因此可以不通過類的實例化而直接引用類中的靜態方法.引用格式如下:
      類名稱::靜態方法名(參數);
      如果你要在類內部的成員方法中調用靜態方法,那麼在靜態方法的名稱前加上操作符: "self::" 即可.在靜態方法中只能調用靜態變量,而不能調用普通變量;而普通方法中則可以調用靜態變量.
使用靜態成員除了不需要實例化外,另一個作用是在對象被銷毀後,仍然保留呗修改的靜態數據,以便下次調用.
  3) clone.對象的克隆可以通過關鍵字來實現.使用clone對象與原對象沒有任何關系,即克隆對象會重新申請一份存儲空間來存放原對象內容.格式如下:
      $克隆對象 = clone $原克隆對象名稱;
    克隆成功後,他們的n成員方法,屬性以及值完全相等.如果要對副本重新初始化,就要用到 _clone().
     魔術方法_clone()可以對克隆後的副本對象重新初始化.它不需要任何參數,其中自動包含$this (副本對象)和 $that (原對象) 對象的引用.
對象的比較:
  "==" 表示比較兩個對象的內容,"==="表示比較兩個對象的引用地址相等.
對象類型的檢測: instanceof 操作符可以檢測當前對象屬於那個對象.

面向對象---常用魔術方法:
以上我們已經了解的常用魔術方法有:_construct(),_destruct(),_clone.下面我們再接著介紹幾個常用魔術方法.
_get(),_set();
  以上兩個方法用於對私有成員精細復制或者獲取值的操作.
  _set()在程序運行中為私有的成員屬性設置值,它不需要任何返回值._set()方法包括兩個不可省略的參數:變量名和變量值.這個方法不需要主動調用,可在方法錢加上prive關鍵字.
  _get():在程序運行中,在對象的外部獲取私有成員的屬性的值.他有一個參數:私有成員屬性名稱.他返回一個允許對象在外部使用的值.此方法同樣不許主動調用.

_isset(),_unset():
  isset()函數用於檢測變量是否存在.而在面向對象中可以通過isset()函數對公有的成員屬性進行檢測,但對私有成員屬性,此函數則不起作用.因此,_isset()函數正是為了起到此作用而創建.格式如下:
  bool _isset(string name);
  _unset()則同樣為了刪除制定的變量和對象的私有成員屬性.格式如下:
  void _unset(string name);//
_call():
  _call()方法的作用是當程序試圖調用不存在或不可見的成員方法時,php會先調用_call()方法來存儲方法名及其參數(方法名和方法參數).其中方法參數是以數組的形式存在.
_toString()方法:
  其作用是當使用echo 或者print輸出對象時,將對象轉化為字符串.
  如果沒有_toString()方法,直接輸出對象時將會發生致命錯誤.
  輸出對象時應注意的是,echo 或print 語句後面直接跟要輸出的對象,中間不要加多余的字符,否則_toSting()將不會被執行.
_autoload()方法:
  將一個獨立的,完整的類保存到一個php頁中,並且文件名和類名保持一致,這是每個開發人員都需要養成的良好習慣.這樣下次在使用的時候就能夠輕松的找到它.但有一種情況:如果要在一個頁面中引進很多的類,就需要使用include_once()函數或者require_once()函數一個個地引入.php5中引入_autoload()方法可以自動實例化需要使用的類.當一個類還沒實例化時,_autoload()會自動到指定的路徑下面自動查找和類名相同的文件.找到則繼續執行,否則報錯.
復制代碼 代碼如下:

<?php
  function _autoload($class_name){
    $class_path = $class_name.'.class.php';
    if(file_exists($class_path)){
      include_once($class_path);
    }else{
      echo '類不存在或者類路徑錯誤';
    }
}
  $class = new Class(); //將會自動加載.
  echo $class; //輸出類內容.如自定義了_toString()方法;則會輸出_toString()中定義的內容.
?>

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved