
批改狀態(tài):合格
老師批語:
靜態(tài)成員、類常量是屬于類本身,不需要實(shí)例化就可以被訪問到,直接使用類名訪問,減少實(shí)例化對象所占內(nèi)存。
static 標(biāo)識(shí)靜態(tài)成員(默認(rèn)為 public,可以不寫)
const 類常量(不能用 define ),通常在類內(nèi)部使用,不建議在類外部使用
在類內(nèi)部,使用 self::訪問靜態(tài)成員(需要加$)、類常量(不需要加$),(不能使用 $this)
__callStatic 當(dāng)調(diào)用不存在或者沒有權(quán)限訪問的靜態(tài)方法時(shí),此魔術(shù)方法會(huì)被調(diào)用
:: 范圍解析符 self::用于類常量 靜態(tài)成員的訪問
class Teacher
{
// 類常量
public const CATES = ['前端', '后端', '全棧'];
// 靜態(tài)屬性
public static $uname;
private static $salary;
// 不加訪問控制,默認(rèn)為 public
static $siteName = 'php中文網(wǎng)';
static $count = 0;
// 構(gòu)造方法,創(chuàng)建對象時(shí)初始化屬性
public function __construct($uname, $salary)
{
//靜態(tài)成員與類的實(shí)例無關(guān) 不能使用$this來訪問 使用self::訪問靜態(tài)成員 類常量
self::$salary = $salary;
self::$uname = $uname;
self::$count++;
}
static function getBK()
{
// 非靜態(tài)成員是對象級(jí)別的存在,靜態(tài)成員是類級(jí)別的存在,隨著類的加載而加載,優(yōu)先于對象存在的,在靜態(tài)方法中無法訪問非靜態(tài)成員(此時(shí)還不存在對象)
return self::$uname . '來自' . self::$siteName . '可以勝任' . join(',', self::CATES) . '的相關(guān)課程';
}
}
$mj = new Teacher('滅絕師妹', 2000);
echo Teacher::$uname; // 滅絕師妹
// 可以使用對象來訪問,但不建議
echo $mj::$uname; // 滅絕師妹
$mj1 = new Teacher('滅絕老師', 5000);
// 實(shí)例化對象會(huì)改變靜態(tài)屬性的值,值為最后一次實(shí)例化的值,也會(huì)改變之前實(shí)例化的對象
echo Teacher::$uname; // 滅絕老師
echo $mj::$uname; // 滅絕老師
//類常量不建議在類外訪問
print_r(Teacher::CATES); // Array ( [0] => 前端 [1] => 后端 [2] => 全棧 )
// 訪問靜態(tài)方法
echo Teacher::getBK(); // 滅絕老師來自php中文網(wǎng)可以勝任前端,后端,全棧的相關(guān)課程
// 訪問次數(shù)
echo Teacher::$count; // 2
接口(interface)是定義,類(class)是實(shí)現(xiàn)。
// 接口(interface)
interface iDemo
{
// 所有成員必須是公開的(public)
public const gender = 'MALE';
// 接口(interface)所有方法都是抽象方法 只有聲明 沒有實(shí)現(xiàn)
public function sum($a, $b);
public function sub($a, $b);
public function mul($a, $b);
public function div($a, $b);
}
interface test
{
public const T = 20;
}
// 抽象類(abstract):
// 抽象類 可以存在 抽象方法和工作方法 不能被實(shí)例化
// 抽象類可以繼承多個(gè)接口
// 實(shí)現(xiàn)部分方法,剩余方法由類(class)完成
abstract class aDemo implements iDemo, test
{
// 重寫接口 iDemo 中的 sum 方法
public function sum($a, $b)
{
return $a + $b;
}
// 重寫接口 iDemo 中的 sub 方法
public function sub($a, $b)
{
return $a - $b;
}
}
// 類只能繼承一個(gè)父類(抽象類)
// 類(class):實(shí)現(xiàn)全部方法,可以實(shí)例化
class Work extends aDemo
{
// 重寫接口 iDemo 中的 mul 方法
public function mul($a, $b)
{
// 調(diào)用接口 test 中的常量 T
echo self::T;
return $a * $b;
}
// 重寫接口 iDemo 中的 div 方法
public function div($a, $b)
{
return $a / $b;
}
}
$obj = new Work;
$obj->mul(5,6); // 20 ( echo self::T; )
echo $obj->sum(10, 20); // 30
trait是基于類的語法,但是和接口一樣,不能被實(shí)例化 ,是對類功能的橫向擴(kuò)展。
php oop 默認(rèn)是單繼承 只能繼承一個(gè)父類->高耦合
// 接上例的接口和抽象類
// 定義 trait,擴(kuò)展類的功能
// 斷點(diǎn)打印 t1
trait t1
{
public function dd($data)
{
var_dump($data);
die;
}
}
// 擴(kuò)展 sum() 功能
trait t2
{
public function sum($a, $b, ...$args)
{
return $a + $b + array_sum($args);
}
}
class Work extends aDemo
{
// 同名方法優(yōu)先級(jí) 類同名方法(重寫)>trait>繼承成員方法
//trait 功能組合式地實(shí)現(xiàn)多繼承
use t1, t2;
// 重寫接口 iDemo 中的 mul 方法
public function mul($a, $b)
{
// 調(diào)用接口 test 中的常量 T
echo self::T;
return $a * $b;
}
// 重寫接口 iDemo 中的 div 方法
public function div($a, $b)
{
return $a / $b;
}
// 類同名方法(重寫),優(yōu)先級(jí)最大
// public function sum($a, $b)
// {
// return 'hello';
// }
}
echo $obj->sum(10, 20, 30, 40, 200); // 300 (trait t2)
$obj->dd('你好'); // 你好(trait t1)
self:: 對當(dāng)前類的靜態(tài)引用是由限制的,self::取決于定義當(dāng)前方法所在的類, 定義類與調(diào)用類(實(shí)例化的對象)不能動(dòng)態(tài)綁定
class Car
{
// 私有靜態(tài)方法 getName()
private static function getName(): string
{
return 'car';
}
public static function run()
{
// self:: 指向當(dāng)前類,實(shí)例化的對象中依然指向當(dāng)前類 Car
return self::getName();
}
}
class Benz extends Car
{
// 重寫父類的靜態(tài)方法 getName()
public static function getName()
{
return 'E300';
}
}
echo Car::run(); // car
// 調(diào)用類中 self::還是指向父類 Car,而不是指向調(diào)用類 Benz
echo Benz::run(); // car
使用后期靜態(tài)綁定 static::,不再被解析為定義當(dāng)前方法所在的類,而是在調(diào)用類。
class Car
{
private static function getName(): string
{
return 'car';
}
public static function run()
{
// self:: 改為 static::
return static::getName();
}
}
class Benz extends Car
{
public static function getName()
{
return 'E300';
}
}
echo Car::run(); // car
// 后期靜態(tài)綁定 static::,不再指向父類 Car,而是指向調(diào)用類 Benz
echo Benz::run(); // E300
全局成員: 常量、命名函數(shù)、類(接口),不受作用域限制,重名的話會(huì)沖突
命名空間:可以解決全局成員命名沖突的問題
namespace ns1;
class test
{
public static function show()
{
// __FUNCTION__ 只是返回方法(或者函數(shù))的名字
// __METHOD__ 返回類名和方法的名字(包括命名空間,如有)
return __METHOD__;
}
}
namespace ns2;
class test
{
public static function show()
{
return __METHOD__;
}
}
// 當(dāng)前在命名空間 ns2,可以直接調(diào)用本空間下的類
echo test::show(); // ns2\test::show
// call_user_func() 回調(diào),是異步,脫離了當(dāng)前線程,不能直接調(diào)用,需要加上命名空間
echo call_user_func(['test', 'show']); // 報(bào)錯(cuò)找不到test類
echo call_user_func(['ns2\test', 'show']); // ns2\test::show
// 從非全局命名空間(當(dāng)前為 ns2)訪問別的空間中的類 先回到root: \
// 注意:這里的反斜杠(\)是空間分隔符,不是目錄分隔符
echo \ns1\test::show(); // ns1\test::show
命名空間下的函數(shù),優(yōu)先級(jí)高于系統(tǒng)同名函數(shù) (系統(tǒng)函數(shù)默認(rèn)在全局命名空間)
namespace demo;
function var_dump($data)
{
echo 'var_dump' . $data;
}
var_dump('你好'); // var_dump你好
目錄結(jié)構(gòu):
app\controller 下面的兩個(gè)類(命名空間設(shè)置為類所在的目錄)
Index.php
namespace app\controller;
class Index
{
static function index()
{
return __METHOD__ . "<br />";
}
}
Login.php
namespace app\controller;
class Login
{
static function index()
{
return __METHOD__ . "<br />";
}
}
autoload.php:類的自動(dòng)加載器
spl_autoload_register(function ($className) {
// 自動(dòng)加載器引入的類名 $className 是帶有命名空間的(app\controller\Index)
// 命名空間名稱與目錄樹對應(yīng),可以參與類文件所在位置的拼接
// 命名空間的反斜杠(\)是空間分隔符,不是目錄分隔符,需要轉(zhuǎn)換為目錄分割符
// "\\":第一個(gè) \ 是轉(zhuǎn)義符,第二個(gè) \ 是空間分隔符
$file = str_replace("\\", DIRECTORY_SEPARATOR, $className) . '.php';
if (is_file($file) && file_exists($file)) require $file;
});
index.php:入口文件,使用 use 引入其他命名空間中的類
// 入口文件
// 注意:入口文件不能放在類所在的目錄,否則無法引入
require __DIR__ . DIRECTORY_SEPARATOR . 'autoload.php';
// 1. 直接調(diào)用其他命名空間中的類,需加上命名空間
// 無需 use app\controller;
// 當(dāng)前為全局命名空間,無需加 root:\
echo app\controller\Index::index(); // app\controller\Index::index
// 如果需要給命名空間起別名,則需要 use as
use app\controller as ac;
echo ac\login::index(); // app\controller\Login::index
// 2. use 引入其他命名空間中的類,然后可以直接調(diào)用改類
use app\controller\Index;
use app\controller\Login;
echo Index::index(); // app\controller\Index::index
echo Login::index(); // app\controller\Login::index
// 給引入的類起別名: use as
// 不起別名,默認(rèn)為Index
use app\controller\Index as in;
echo in::index(); // app\controller\Index::index
微信掃碼
關(guān)注PHP中文網(wǎng)服務(wù)號(hào)
QQ掃碼
加入技術(shù)交流群
Copyright 2014-2025 http://ipnx.cn/ All Rights Reserved | php.cn | 湘ICP備2023035733號(hào)