首頁 >後端開發 >php教程 >PHP什麼是物件導向? PHP物件導向小結

PHP什麼是物件導向? PHP物件導向小結

青灯夜游
青灯夜游轉載
2018-10-18 15:52:195289瀏覽

本篇文章帶給大家的內容是PHP什麼是物件導向? PHP物件導向小結。有一定的參考價值,有需要的朋友可以參考一下,希望對你們有幫助。

 物件導向特性:

*重複使用(每個模組都可以在專案中重複使用)

*彈性(每個模組都很輕鬆被替換更改的)

*拓展性(在模組上添加新功能是很方便的)

類別和對象的關係(類生成對象)

物以類聚:相同特性的物件歸為一個類,例如nba球員,都有想到的屬性姓名,身高體重,球隊號碼,方法有跑步,跳躍,運球,投籃。將他們當做一個類,而喬丹,詹姆斯這些就是nba球員的實例,也叫對象;

對象內部高內聚(特定的職能,所有相關的內容都封裝在對象內部),對外低耦合(物件的一些可見屬性和一些可見方法)

用class 宣告一個類,在類別裡面只能有 成員屬性 和 成員方法! ! ! !不能有其他,在一個腳本中不能有兩個同名類別,實例化類別可以有多個物件

class Computer{
    public $text = "用关键字new实例化一个类";
    public function output(){
    echo $this->text;
    }
}
$computer = new Computer();

$computer->output();//外部访问方法
$computer->text();//外部访问属性
$computer2 = new Computer();//可以实例化多个

 類別的屬性和方法

存取控制:
public 公有都可以存取
private 私有  只有類別本身內部可以存取
protected  受保護繼承的子類別和類別本身內部可以訪問,外部存取不了,如: $computer->output() ;如果output()方法設了protected,則報錯。

類別裡面的方法:

方法裡面呼叫一個屬性,需要實例化類別才能存取屬性,而$this可以理解為是這個類別的一個實例

class Computer{    
    public $text = "用$this调用我";   
    public function output(){    
         echo $this->text;
    }
}

建構方法(實例化時執行)

 建構方法可以傳遞參數,在實例化時傳入

 透過建構函數的參數傳遞,改變裡面的屬性使得每個實例物件不同

class Computer{
   function __construct($arg){
       echo "我是构造方法,自动执行";    
       echo $arg;
   } 
} 
$conputer = new Computer("我是构方法的参数");

 析構方法:銷毀時執行,不能有參數

程式結束後自動執行,手動釋放(當物件的參考全部銷毀時)會使析構函數提前執行,不用等到程式結束後才呼叫

當你unset 一個引用,只是斷開了變數名稱和變數內容之間的綁定。這並不意味著變數內容被銷毀了 

//对象引用  在PHP 中引用的意思是:不同的名字访问同一个变量内容.
class A
{
    
    function __destruct()
    {
        echo '====我是析构函数====';
    }
}


$a = new A();
//提前执行析构函数的两个方法 unset($a);$a=null;
echo "====正常执行我是先输出的=====";
//两种对象引种的区别
$a = $b;//这时$a和$b是两个独立的引用,unset($aa)只是删除了$a的引用,还有$b的引用,所以不会执行析构函数。改变其中一个为null,不会影响另外一个变量,也不会执行析构函数;
$c = &$a;//两个的变量使用同个引用,c是a的影子,改变其中一个变量为null,两个都为null,会执行析构函数。但是只是unset($a),$c还在使用引用,只要有引用在不会执行析构函数;
//对象的引用用于访问对象的属性和方法,所以$a $b $c都可以访问对象的属性方法; 
//当一个对象的所有引用被删除后,才会触发析构函数

//总结:如果程序大,对象引用尽量使用&,节省内存,清除也方便。设其中一个为Null,其他都为Null;

//变量引用 (默认变量赋值会独立开辟一个内存存放内容)
 //PHP 的引用允许你用两个变量来指向同一个内容
$a="AB"; 
$b =&$a;
echo $a;//这里输出:AB
echo $b;//这里输出:AB 
$b="EF"; 
echo $a;//这里$a的值变为EF 所以输出EF 
echo $b;//这里输出EF  <?php
$a = 1;
$b = $a;
echo $a;
//在此之前,b都是和a共用内存空间的。
xdebug_debug_zval(&#39;b&#39;);
$a = 2;//a作出了改变,此时b才会有自己的空间
xdebug_debug_zval(&#39;b&#39;);
?>


//函数引用
<?php
function test(&$a){ 
$a=$a+100; 
} 
$b=1; 
echo $b;//输出1 test($b); //这里$b传递给函数的其实是$b的变量内容所处的内存地址,通过在函数里改变$a的值 就可以改变$b的值了 echo "<br>"; echo $b;//输出101
?>//函数的引用返回
<?phpfunction &test(){     static $b=0;//申明一个静态变量     $b=$b+1;     echo $b;     return $b; }$a=test();//这条语句会输出 $b的值 为1 相当于$a=$b$a=5; $a=test();//这条语句会输出 $b的值 为2 也是$a=$b$a=&test();//这条语句会输出 $b的值 为3 $a=&$b,所以b会随a变了$a=5; $a=test();//这条语句会输出 $b的值 为6?>

賦值和複製的區別

$a=$b(獨立引用)和$a=&$ b(同一引用)這種賦值方式,指向的是同一個對象,同一塊記憶體空間;

$a=clone $b這種賦值方式,則是指向另一個新的對象,另一個塊新的記憶體空間。

<?phpclass mm {

    public $name = &#39;Peter&#39;;

}
$a = new mm();
$b = $a; 
$c = &$a;
$d = clone $a; 
$b->name = "Anne";
echo $a->name,"\n",$b->name,"\n",$c->name,"\n",$d->name;//输出为:Anne Anne Anne Peter
?>

類別常數 

內部存取self::常數名稱

外部存取不需要實例化:類別名稱::常數名稱

class Computer{    
    const yh = 12;    
    const yh2 = self::yh+1;
} 
var_dump (Computer::yh2);

$this 和self 的區別

一個是物件$this 相當於實例化後,可以說除了靜態和const常數,基本上其他都可以使用this聯絡;

self則是類別本身self可以存取本類別中的靜態屬性和靜態方法,可以存取父類別中的靜態屬性和靜態方法。用self時,可以不用實例化的

類別的繼承

#存在意義:把相同的屬性方法抽出來,讓子類別繼承

extends 後面只能一個逗號,就是說只能繼承一個父類,當單繼承

class dad{     
     function eat(){         
          echo "我是父类的方法,子类可以继承我的方法";
     }
}
class boy extends dad{
} 
$boy = new boy();$boy->eat();

子類別也可以覆寫父類別的方法

子類別沒有建構方法時,就會調用父類別的建構方法,有則呼叫自己的,
用關鍵字parent:: __construct();可以呼叫父類別的建構方法
用final關鍵字加在類別前面就不會被繼承;加到方法面前,此方法就不會被重寫

命名空間(解決命名衝突問題)
利用檔案系統不用目錄的原理
被引入的php文件中加入 namespace 目錄\子目錄;
使用時呼叫:new 目錄\子目錄\類別名稱();如new com\session\computer();
受命名空間影響的有,類別(包括抽象類,traits),接口,函數,常數(const和define都是用來聲明常數的(它們的區別不詳述),但是在命名空間裡,define的作用是全局的,而const則作用於當前空間。)

要注意的是,目前腳本檔案的第一個命名空間前面不能有任何程式碼,下面的寫法都是錯誤的:

//例一
//在脚本前面写了一些逻辑代码
 

<?php

$path = "/";

class Comment { }

namespace Article;

?>

 

//例二
//在脚本前面输出了一些字符

<html></html>
<?php

namespace Article;

?>为什么要说第一个命名空间呢?因为同一脚本文件中可以创建多个命名空间。<?php
//创建一个名为&#39;Article&#39;的命名空间namespace Article;
//此Comment属于Article空间的元素class Comment { }
//创建一个名为&#39;MessageBoard&#39;的命名空间namespace MessageBoard;
//此Comment属于MessageBoard空间的元素class Comment { }?>

由於每次呼叫都要寫上路徑,很麻煩,所以出現use的用法(use引入必須帶類名或函數名)
在呼叫時先用use引入,use 目錄\子目錄\類;還可以起個別名區別as

use venter\session\computer;
use venter\computer as computer2;
new computer();
new computer2();

函数的话记得带上function
use function venter\session\computer;
computer();

常量记得带上const 
use const venter\session\computer;
var_dump(computer);

重點:在命名空間裡面呼叫全域的類,函數,常數的區別,
頁面a定義了命名空間namespace venter;引入b頁面(全域空間)後,此時想呼叫b頁面的類,必須:
New \venter() 加個\代表全域空間下的
但是當呼叫函數和常數時,就不需要加,因為他會自動尋找,向全域尋找。

类自动加载:
当你实例化一个类时,这个类不存在,就会自动执行我们写的 function __autoload($className){},在这个自动函数的内部去执行我们想要操作的代码,参数就是我们实例化的类名,因此可以根据参数去引入php文件。
__autoload将被淘汰,使用新的函数 spl_autoload_register();参数可以传函数名或者匿名函数


spl_autoload_register(function($a){
echo $a;
}
);
new Computer();
或者
function aaa($a){
echo $a;
}

spl_autoload_register('aaa');
new Computer();
或者类的调用方法
class momo
{
function aaa($a){
echo $a;
}
}
spl_autoload_register([new momo],'aaa');
new Computer();

利用命名空间和自动加载实现项目自动引用
1,文件目录就和命名空间名一样,文件名和类名一样 new models\imooc() 就是在models文件下的imooc.php文件,
2,然后利用spl_autoload_register(function($classname){
include str_replace("\\","/",$classname.".php");
});
这里的作用是models\imooc替换掉models/imooc.php 引入
而imooc.php文件中必须命名 namespace models;

static 静态

存在的价值,为了让对象公用一些数据,做到统一性

当属性和方法被定义为 static 时就变成类的属性和方法,不属于对象的,不需要实例化

外部访问  类名::$aa  内部访问 self::$aa 或者static::$aa; 子类访问父类 parent::$aa;

静态方法不能调用非静态属性
因为 $this代表实例化对象,而这里是类,不知道 $this 代表哪个对象


class person{
public static $aa ="a";
public static function eat(){
        echo self::$aa;
        echo static::$aa;
    }
}
class boy extends person{
    public function eat2(){
        echo parent::$aa;
    }
}
echo(boy::eat2());

后期静态绑定:

class A{
public static function who(){
echo "A类的who方法";
}
public static function test(){
self::who(); 
// static::who();
}

}
class B extends A{
public static function who(){
echo "B类的who方法";
}
}
B::test();

如果是self::who(); 输出的是A类的who方法,说明调用的是A自身,static::who();会根据上下文作处理,类B调用就使用B里面的who()

魔术方法
__set($var,$val) 设置私有属性,当外部调用设置一个私有属性时会自动执行这个方法,
__get($var)获取私有属性,原理是外部调用一个私有属性时会自动执行这个方法
例子:


class test{
private $abc = "";
private $ccc = "";
public function __set($var,$val){
$this->$var = $val;
}
public function __get($var){
return $this->$var;
}
}
$test = new test();
$test->abc = 'abc';
var_dump($test->abc);

__isset($var)方法,当外部调用isset($test-abc)访问一个不能访问的属性时,就会自动执行   isset()或者empty() 都会触发__isset()方法

__unset($var),当外部想删除一个私用属性时,会自动执行

以上是属性的重载

__call,__callStatic是属于方法的重载,不是重写

__call($func方法名,$arguments参数)当外部调用一个没有定义的方法时,就会调用

__callStatic($meethod,$arg)当调用一个不存在的静态方法时,会自动执行 注意在function 前也要加入 static 因为是静态方法

__invoke($rag)当实例化一个类后,把这个对象变量当成函数调用时,会自动执行
例如:$test = new test();
$test("go....");

__toString() 当对象被当成string使用时,会执行,比如 echo($test);

__clone方法的一些应用
当一个对象被克隆时,会调用__clone,此时可以在里面执行一些逻辑,比如不想让某些值被克隆,或者初始化一些属性的值

对象拷贝:
浅拷贝:是地址传递(对象是浅拷贝)
深拷贝:复制一份,新开辟一块内存(普通变量是深拷贝)

加clone 使对象成为深拷贝,互不影响;
$a = new A();
$b = clone $a;

__clone()当使用clone时,会自动执行
$a = new A();
$b = clone $a; 在A类中会执行__clone()
例子:

class A{
public $obj = null;
public function __clone(){
$this->obj = clone $this->obj;//开辟了新空间给克隆的对象
}
}
Class B{
public $sex = 0;
}

$a = new A();
$a->obj= new B();
$b = clone $a;
$b->obj->sex = 1;
var_dump($a->obj->sex);

类型约束

class A{
public $obj = null;
public function go(){
echo "googogogogo";
}
}
class B{
public function go(){
echo "bbbbbb";
}
}
Function test(A $a){
$a->go();
}
test(new A());//必须是A的实例

trait 关键字

解决单继承问题 配合use 使用

trait A{
public function a(){
echo "aaaaa";
}
}
trait B{
public function b(){
echo "bbbb";
}
}

Class test{
use A,B;
public function c(){
echo "cccc";
}
}

$test = new test();
$test->a();
$test->b();
$test->c();

接口

可以理解为类的模板 不能直接被实例化

用instanceof 判断某个对象是否实现了某个接口
接口可以继承接口,但是类必须实现接口所有的方法

interface person {
public function eat();
public function sleep();
}
class man implements person{
public function eat(){
echo "chichi吃吃";
}
public function sleep(){
echo "shuishushi";
}
}
$aaa = new man();
$aaa->eat();
//接口继承 两种方法 
interface aa {
public function eat();
}
interface bb {
public function sleep();
}
interface person extends aa,bb{
//person就直接继承了两种方法
}
class man implements person{
public function eat(){
echo "chichi";
}
public function sleep(){
echo "shuishuishui";
}
}
//或者 直接实现两种接口
class man implements aa,bb{
public function eat(){
echo "chichi";
}
public function sleep(){
echo "shuishuishui";
}
}
//接口里面可以利用 const 定义一个常量 
interface person {
const aa = "bbb";
public function eat();
public function sleep();
}
echo person::aa;

抽象类

(比如人和动物都会呼吸方法都一样,此时就不需要每个类去实现不同的呼吸方法,吃东西的方法不同,所以在类中各自实现逻辑)抽象类的子类只需要实现抽象方法;

内部有自己的执行方法

abstract class person {
public function holiday(){
echo '我是抽象类自己实现的方法';
}
//抽象方法,以分号结束,无方法体;抽象类中至少要有一个抽象方法
abstract public function eat();
}
class man extends person{
    public function eat(){
    $this->holiday();//直接调用即可
    }
}
$aaa = new man();
$aaa->eat();

单例模式:

让一个类只会被实例化一次,节省内存空间
先把构造函数和克隆函数变成私用属性

class test{
private static $_instance = null;//依靠属性存储实例对象判断是否已经实例过
private function __construct(){
// 私有后将不会被外部实例
}
private function __clone(){
// 私有后将不会被外部克隆
}
public static function getInstance(){
if(!(self::$_instance instanceof self)){
// instanceof判断是否是当前的实例,不是的话就实例化赋值,否则就返回
self::$_instance = new self();
}
return self::$_instance;
}
}
$test1 = test::getInstance();
$test2 = test::getInstance();
$test3 = test::getInstance();
var_dump($test1);
var_dump($test2);
var_dump($test3);
// 输出结果object(test)#1 (0) { } object(test)#1 (0) { } object(test)#1 (0) { }

工厂模式:

就是在多处实例化一个类,当这个类名需要改变时,就会导致大量地方需要更改,使用工厂模式避免这种情况发生

class A{
public function a(){
echo 'aaa';
}
public function c(){
echo 'ccc';
}
public function b(){
echo 'bbb';
}
}
class cashe{
public static function factory(){
return new A();//当业务逻辑变化时,只需要改此处
}
}
$cashe = cashe::factory();
$cashe->a();

面向对象功能汇总

有继承功能,必须有访问的控制,(私有公有属性),static静态关键字来保存一些公用的数据,重写对父类的方法属性重定义,final关键字不允许重写或者继承,访问静态属性的几个方法,接口中的方法是不用具体实现的,在类中才实现,而且必须实现接口中所有的方法,因为有了不同的实现方法逻辑,不同的对象产生不同的表现,这叫多态,存在与接口与类之间的叫抽象类,可以有一部分可以实现,一部分不用实现

/*--------------多态的一个应用实例 模拟USB设备的使用------------------*/

//一个USB的接口

interface USB{

function mount();//装载USB的方法

function work();//USB工作的方法

function unmount();//卸载USB的方法

}

//定义一个USB设备 U盘

class Upan implements USB{//实现USB接口

function mount(){

echo " U盘 装载成功<br/>";

}

function work(){

echo "U盘 开始工作<br/>";

}

function unmount(){

echo "U盘 卸载成功<br/>";

}

}

//定义一个USB设备 USB鼠标

class Umouse implements USB{//实现USB接口

function mount(){

echo " USB键盘 装载成功<br/>";

}

function work(){

echo "USB键盘 开始工作<br/>";

}

function unmount(){

echo "USB键盘 卸载成功<br/>";

}

}

//定义一个电脑类

class Computer{

//使用USB设备的方法

function useUSB ($usb){//$usb参数表示 使用哪种USB设备

$usb->mount();//调用设备的 装载方法

$usb->work();//调用设备的 工作方法

$usb->unmount();//调用设备的卸载方法

}

}

//定义一个电脑的使用者的类

class PcUser{

//

安装

USB的方法

function install(){

//首先拿来一台电脑

$pc=new Computer;

//拿来一些USB设备

$up=new Upan;//拿来一个U盘

$um=new Umouse;//拿来一个USB鼠标

//把USB设备插入电脑, 使用电脑中使用USB设备的方法 来调用 要插入的设备

$pc->useUSB($up);//插入U盘

$pc->useUSB($um);//插入USB鼠标

}

}

//实例化一个电脑用户

$user=new PcUser;

$user->install();//安装设备

/*-------------输出内容--------------

U盘 装载成功

U盘 开始工作

U盘 卸载成功

USB键盘 装载成功

USB键盘 开始工作

USB键盘 卸载成功

-----------------------------------*/

?>

以上就是本篇的全部内容,更多相关教程请访问php编程从入门到精通全套视频教程php实战视频教程bootstrap视频教程


以上是PHP什麼是物件導向? PHP物件導向小結的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:cnblogs.com。如有侵權,請聯絡admin@php.cn刪除

相關文章

看更多