PHP之面对对象

PHP面对对象

什么是面对对象

简单通俗的说一下什么是面向过程和面向对象

类的概念:

  • 类是由相同属性和方法构成
  • 一个类可以产生千千万万个对象

对象的概念:

  • 对象也是属性(特征)和方法(行为)构成的
  • 先有类,后有对象
<?php
// 定义 Student类
class Student {
    // 成员属性
    public $name = 'Taoy';
    public $age = 18;
    // 成员方法
    public function display(){
        echo "{$this->name} 的年龄是 {$this->age}岁<br />";
    }
}

类的成员属性

类中只有两个内容,分别为:成员属性和成员方法。类的成员就是对象,因此,又称为“对象属性”“对象方法”。

访问修饰符

作用:主要用来保护数据安全

  • public(公共权限):在任何地方都可以访问,主要指类内部、类外部、子类中都可以访问。
  • protected(受保护的权限):只能在本类中、子类中被访问,在类外不能访问。
  • private(私有的权限):只能在本类中被访问,在类外、子类中都无权访问。

类的成员方法

  • 成员方法,就是普通函数
  • 成员方法可以省略权限控制符,默认为 public
<?php
// 成员方法的定义格式
权限控制符 function 函数名称(形参...){
    // 方法的功能代码:
    [return 参数] // 可选
}

举例:

<?php
// 定义 hello 类
class hello{
    // 成员方法(对象方法)
    public function say($name, $age){
        $str = "My name is {$name}, {$age} years old.";
        // 返回介绍的字符串
        return $str;
    }
}
?>

类的实例对象

  • 类可以产生 N 多个对象
  • new关键字来创建类的对象
# 语法格式
<?php
//创建类的对象的语法(类的实例)
$obj1 = new ClassName; //无参数无括号
$obj2 = new ClassName(); //无参数有括号
$obj3 = new ClassName(实参1,实参2...); //有参数有括号
?>

注意:对象不能单独存在,对象必须归属于哪个类。没有类,一定没有对象

例子:

<?php
// 定义 hello 类
class hello{
    // 成员方法(对象方法)
    public function say($name, $age){
        $str = "My name is {$name}, {$age} years old.";
        // 返回介绍的字符串
        return $str;
    }
}
$h = new hello; // new hello() 也可以
echo $h->say('Taoy', 19);  // 输出:My name is Taoy, 19 years old.
?>

对象属性的操作

对象属性的操作:增加,删除,修改,读取

<?php
// 定义 Student 类
class Student{
    // 成员属性(对象属性)
    public $name = 'Taoy';
    public $age = 18;
}
// 类的实例
$obj = new Student();

//1. 修改对象的属性:对已存在的属性重新赋值
//$obj->$name表示访问$name变量的属性
// $obj访问属性,属性不加$符号
$obj->name = 'bob';
$obj->age = 19;

// 2. 添加属性,给不存在的属性赋值
$obj->edu = 'B';
$obj->country = "China";

// 3. 删除属性
unset($obj->edu, $obj->country);

// 4. 读取属性值
echo "{$obj->name} 的年龄是 {$obj->age} 岁"; 

# 输出: bob 的年龄是 19 岁  // 前面有修改值
?>

伪变量$this使用

$this变量含义

  • PHP 中$this 变量代表当前对象
  • $this代表当前对象,用来调用对象的属性和方法
  • $this 只能在成员方法中存在,其它地方都不能使用
<?php
header("Content-Type: text/html;charset=utf-8");
// 定义 一个 student 类
class Student{
    // 私有成员属性
    private $name = 'Taoy';
    private $age = 18;

    // 私有成员方法 返回一条水平线
    private function showLine(){
        return "<hr>";
    }

    // 成员方法(对象方法)
    public function display(){
        $str = "<h3>{$this->name}的信息如下</h3>";
        $str .= $this->showLine();
        $str .= "{$this->name} 的年龄是 {$this->age}";
        echo $str;
    }
}
$s = new Student;
$s->display();
?>

上面程序输出:

Taoy的信息如下
------------------
Taoy 的年龄是 18

定义类的常量

  • 常量:值就是值永远不变的量,常量不能修改,常量也不能删除
  • 类常量定义使用 const 关键字。define()定义的常量为全局常量
  • 类常量,只能通过类名来调用( 名:: 常量);成员的东西,只能通过对象来调用
  • 访问类常量,是通过 范围解析符(::)来访问类的常量。例如:Student::Name
  • 类常量在内存中只有一份,不会随着对象的增加而增加。类常量可以被所有对象共享
# 定义格式
<?php
/*类常量的定义格式
const 常量名 = 常量值
语法说明:
(1)常量没有权限访问符
(2)const定义的常量,一般认为局部常量
(3)常量名不加$符号,尽量全大写
(4)常量的值,必须是一个固定的值
?>

例子:

<?php
header("Content-Type: text/html;charset=utf-8");
class SQL{
    const DB_HOST = 'localhost';
    const DB_USER = 'root';
    const DB_PASS = 'password';

    public function display(){
        $str = "主机名:".SQL::DB_HOST;
        $str .= "<br> 用户名:".SQL::DB_USER;
        $str .= "<br> 密码:".SQL::DB_PASS;
        echo $str;
    }
}
// 直接访问类常量:静态化调用方式
$str = "主机名:".SQL::DB_HOST;
$str .= "<br> 用户名:".SQL::DB_USER;
$str .= "<br> 密码:".SQL::DB_PASS;
echo $str.'<hr>';

$sql = new SQL();
$sql->display();
?>

上例代码输出:

主机名:localhost
用户名:root
密码:password
-----------------
主机名:localhost
用户名:root
密码:password

静态属性和静态方法

  • static 关键字修饰的属性,就是静态属性;
  • static 关键字修饰的方法,就是静态方法;
  • 静态属性和静态方法,是通过“类名::静态属性或静态方法”方式来访问的
  • 静态属性的值是可以改变的,可以被所有对象共享
  • 静态属性和静态方法,是有权限限制的。
<?php
header("Content-Type: text/html;charset=utf-8");

class Student{
    //公共的静态属性(类的属性)
    static public $title = "<h3>This is A title</h3>";
    //私有的静态方法(类的方法)
    private static function showline(){
        return "<hr>";
    }
    //公共的成员方法
    public function ShowInfo($Name, $Age){
        $str = Student::$title;
        $str .= Student::showline();
        $str .= "{$Name} 的年龄是{$Age}岁。";
        echo $str;
    }
}
$s = new Student();
$s->ShowInfo('Taoy', 19);

$b = new Student();
$b->ShowInfo('bob', 18);

代码输出:

This is A title
Taoy 的年龄是19岁。
------------------
This is A title
bob 的年龄是18岁。

构造方法

什么是构造方法?

  • 当销毁一个对象前,自动调用的方法,就是析构方法;
  • 析构方法的名称是固定的:__destruct()
  • 析构方法一定没有参数,析构方法一定是成员中方法;
  • 析构方法的作用:垃圾回收。例如:可以断开数据库的连接、在线人数等
<?php
header("Content-Type: text/html;charset=utf-8");

//定义Demo类
class Demo{
    public function __destruct(){
        echo "对象即将销毁!"."<br>";
    }
}
//创建Student类对象
$obj = new Demo;
unset($obj);         // 手动销毁
echo "End..."."<br>";
?>

输出:

对象即将销毁!
End...

OOP(面对对象) 中内存的分配情况

值传递

PHP有8种数据类型:

  • 标量数据类型:字符串型、整型、浮点型、布尔型
  • 复合数据类型:数组、对象
  • 特殊数据类型:资源、NULL

其中,字符串型、整型、浮点型、布尔型、数组,默认都是 值传递

对象、资源,默认都是 引用传递

值传递定义:将一个变量的“值”,复制一份,传递给另一个变量;两个变量之间没有任何关系;
修改其中一个变量的值,另一个变量不会改变。

<?php
$a = 100;
$b = $a;
$a = 200
echo "\$a = $a, \$b = $b";

# 输出结果: $a = 200, $b = 100
?>

引用传递

“引用传地址”将一个变量的“数据地址”,复制一份,传递给另一个变量;两个变量指向了“同一数据”;
修改其中一个变量的数据,另一个变量也会一起变

<?php
class Info{
    public $Name = 'Taoy';
    public $Age = 19;
}

$info1 = new Info();

var_dump("<pre>");
var_dump($info1); // 为修改前的数据

$info2 = $info1;    // 引用传递
$info2->Name = 'bob';     // 修改成员属性
var_dump($info2); 

var_dump($info1);
?>

上面代码输出:

string(5) "
"
object(Info)#1 (2) {
  ["Name"]=>
  string(4) "Taoy"
  ["Age"]=>
  int(19)
}
object(Info)#1 (2) {
  ["Name"]=>
  string(3) "bob"     //    这里
  ["Age"]=>
  int(19)
}
object(Info)#1 (2) {
  ["Name"]=>
  string(3) "bob"    // 这里
  ["Age"]=>
  int(19)
}

类的封装

什么是类的封装?

  • 类的封装性:将敏感数据保护起来,不被外界访问。
  • 类的封装性实现,就是通过权限控制符来实现
  • 在项目中,所有成员属性,一般都是 privateprotected 权限

访问权限修饰符 (前面有提到,这里略)

<?php
class Book{
    // 类常量定义
    const TITLE = "<h3>---Book---</h3>";

    // 私有的静态属性
    private static $count = 0;
    
    // 私有的图书信息(属性)
    private $Name;
    private $Author;
    private $Price;

    // 构造方法: 用于对象初始化
    public function __construct($arr){
            $this->Name = $arr['Name'];
            $this->Author = $arr['Author'];
            $this->Price = $arr['Price'];
            self::$count++;
    }
    // 水平线
    protected static function ShowLine(){
        return '<hr>';
    }
    // 显示图书信息
    public function ShowInfo(){
        $str = self::TITLE;
        $str .= self::ShowLine();
        $str .= "BookName: {$this->Name}<br />";
        $str .= "Author: {$this->Author}<br />";
        $str .= "Price: {$this->Price}<br />";
        $str .= "There are ".self::$count." books now";
        return $str;
    }

}
$php_book = array(
        'Name' => 'PHP ...',
        'Author' => 'moumou',
        'Price' => 99.99,
);

$b = new Book($php_book);
echo $b->ShowInfo();

输出:

---Book---
BookName: PHP ...
Author: moumou
Price: 99.99
There are 1 books now

类的继承

继承的相关概念

  • 继承:如果一个 B 类拥有了 A 类的所有特征信息,则我们就认为 B 类继承了 A 类
  • 为什么继承?继承是为了实现功能的升级和扩展。
  • 如果项目需要升级和扩展功能, 不能直接修改原类
# 继承的语法格式
<?php
//继承的语法格式
class SubClass extends ParentClass{
//子类的功能代码
}
语法说明:
(1)subCLass代表是要创建的子类的名称
(2)extends 是继承的关键字,不区分大小写
(3)ParentClass代表已经存在的父类或上层类
?>
<?php
class A{
    public $Name = 'Taoy';
    protected $Age = 19;
    private $Score = 59;
}

class B extends A{
    public function ShowInfo(){
        echo "{$this->Name}<br />";
        echo "{$this->Age}<br />";
        echo "{$this->Score}<br />";     //报错 private(私有权限):只能在本类中被访问。

    }
}
$b = new B();
$b->ShowInfo();

代码输出:

Taoy
19
Notice: Undefined property: B::$Score in ...\demo.php on line 12

构造方法和析构方法的继承

<?php
header("Content-Type: text/html;charset=utf-8");

class A{
    private $name;
    private $age;

    // 构造方法
    public function __construct($Name, $Age){
        $this->name = $Name;
        $this->age = $Age;
    }
    // 显示信息函数
    public function ShowInfo(){
        echo "{$this->name} 年龄是 {$this->age}.";
    }
}

class B extends A{}

$b = new B("Taoy", 19);
$b->ShowInfo();  // 程序输出:Taoy 年龄是 19.
?>

parent 关键字

  • self 代表当前类,parent代表父类
  • self可以调用本类的内容:类常量、静态属性、静态方法、成员方法;
  • parent 可以调用父类的内容:类常量、静态属性、静态方法、成员方法;
<?php

header("Content-Type: text/html;charset=utf-8");

class A{
    const INFO = "A";
    public static $Name = 'a';
}
class B extends A{
    const INFO = "B";
    public static $Name = 'b';

    public function display(){
        echo "父类的常量: ".parent::INFO.'<br />';
        echo "子类的常量: ".self::INFO.'<br />';
        echo "父类的静态属性: ".parent::$Name.'<br />';
        echo "子类的静态属性: ".self::$Name.'<br />';
    }
}

$b = new B;
$b->display();
?>

上例代码输出:

父类的常量: A
子类的常量: B
父类的静态属性: a
子类的静态属性: b

类的多态

  • 类的多态,就是的类的多种形态
  • 类的多态,主要指方法重载和方法重写;
  • 方法重写:父类有一个方法,在子类用同样的名称再定义一次
<?php
function a(){}
function a(){} //php不支持函数重名或方法重名

// 报错:atal error: Cannot redeclare a() (previously declared in ...
?>

方法重写要求

重写前提:先继承在重写

  • 子类中重写的方法名称,要与父类方法名称一致
  • 子类中重写的方法的权限,不能低于父类方法的权限

    • 如果父类方法权限为 public,则重写方法必须是 public
    • 如果父类方法权限为 protected,则重写方法必须是 publicprotected
    • 如果父类方法权限为 private,则子类无法继承,无法继承
<?php

header("Content-Type: text/html;charset=utf-8");

// 重写前提:先继承在重写
class A{
    protected static function ShowInfo($name, $age){
        echo "{$name} 的年龄是{$age}";
    }
}

class B extends A{
    public static function ShowInfo($Name, $Age){
        echo "---INFO---<br />";
        parent::ShowInfo($Name, $Age);
        echo '<br>end....';
    }
}
// 直接类名调用静态方法
B::ShowInfo('Taoy', 19);

?>

代码输出:

---INFO---
Taoy 的年龄是19
end....

构造方法重写

<?php

header("Content-Type: text/html;charset=utf-8");

class Shop{
    private $name;
    private $price;

    // 受保护的构造方法
    protected function __construct($name, $price){
        $this->name = $name;
        $this->price = $price;
    }

    protected function ShowInfo(){
        $str = "商品名称: {$this->name}";
        $str .= "<br>商品价格: {$this->price}";
        return $str;
    }

}

class phone extends Shop{
    private $brand;

    public function __construct($name, $price, $brand){
        // 调用父类的构造方法,传参调用
        parent::__construct($name, $price);
        $this->brand = $brand;
    }
    public function ShowInfo(){
        $str = parent::ShowInfo();
        $str .= "<br>手机品牌: {$this->brand}";
        echo $str;
    }
}

$Huawei = new phone('华为 Honor', 1888.00, "HUAWEI");
$Huawei->ShowInfo();

代码输出:

商品名称: 华为 Honor
商品价格: 1888
手机品牌: HUAWEI

最终类和最终方法

  • Final 关键字修饰的类,就是最终类;
  • Final 关键字修饰的方法,就是最终方法;
  • 最终类:该类不能被继承,直接实例化
  • 最终方法:该方法不能被重写,直接调用即可
<?php
final class A{}

class B extends A{}     // 报错
?>

报错:Fatal error: Class B may not inherit from final class (A) in ... on line 4 # 最终类不能被继承

<?php

class A{
    final public function a(){}
}
class B extends A{
    public function a(){}    // 报错
}

Fatal error: Cannot override final method A::a() in ... on line 8 # 最终方法不能被重写

抽象类和抽象方法

  • abstract 关键字修饰的类,就是抽象类;
  • abstract 关键字修饰的方法,就是抽象方法;
  • 抽象类:该类只能被继承,不能直接实例化。
  • 抽象方法:该方法没有方法体,抽象方法必须先继承,后重写。
<?php
header("Content-Type: text/html;charset=utf-8");

// 定义 抽象 Shop类
abstract class Shop{
    // 抽象方法
    abstract protected function ShowInfo($a, $b);
    abstract protected function README();
}
// 定义手机类,并继承为最终类
final class phone extends Shop{
    // 重写 ShowInfo()抽象方法
    public function ShowInfo($name, $price){
        echo "{$name} 手机 {$price} 元";
    }
    // 重写 README()抽象方法
    public function README(){
        echo "<br>这是成员方法: ".__METHOD__;
        echo "<br>当前函数是:".__FUNCTION__;
    }
}
$Honor = new phone();
$Honor->ShowInfo('honor 99', 9999);
$Honor->README();

代码输出:

honor 99 手机 9999 元
这是成员方法: phone::README
当前函数是:README

参考资料:抽象类、接口 分别使用场景 , 抽象类和接口的区别以及使用场景

接口技术

  • PHP 只支持单继承
  • 接口就是特殊的抽象类
  • interface 关键字,用来声明一个接口。
  • implements 关键字,创建一个子类,来实现接口
  • 接口中只能存在两样东西:类常量、抽象方法
  • 接口中的方法,默认都是抽象方法,因此,不加 abstract 关键字
  • 接口中方法的权限,必须是 public
  • 接口中所有的抽象方法,在子类中必须要重写;
  • 接口中的常量不能重写,只能继承
<?php
header("Content-Type: text/html;charset=utf-8");

// 定义第一个接口
interface Inter1{
    public function ShowInfo($a, $b);
}
interface Inter2{
    public static function README();
}

// 创建抽象的 学生信息类, 并实现多接口
abstract class Student implements Inter1, Inter2{
    // 重写接口 ShowInfo()方法
    public function ShowInfo($Name, $Age){}

    public static function README(){}
}
// 创建 ItStudent 类,继承抽象类
final class ItStudent extends Student{}
// 创建 类对象
$s = new ItStudent();

实例:

<?php
header("Content-Type: text/html;charset=utf-8");

interface Phone{
    // 打电话
    public function tell();
}

interface Mp3{
    // 听音乐
    public function music(); 
}

// 定义 Mp4接口 继承 Mp3
interface Mp4 extends Mp3{
    // 看电影
    public function film();
}


// 定义类并实现继承多个接口
class Honor implements Phone, Mp4{
    // 重写 tell() 抽象方法
    public function tell(){
        echo "Phone!";
    }
    // 重写 music() 抽象方法
    public function music(){
        echo "<br> Listening to music";
    }
    // 自定义 玩游戏 方法
    public function game(){
        echo "<br> playing games!";
    }
    public function film(){
        echo "<br>Watching film";
    }

}

// 创建 Honor 类对象
$h = new Honor();
$h->tell();
$h->music();
$h->game();
$h->film();

代码输出:

Phone!
Listening to music
playing games!
Watching film

自动加载类函数(__autload())

  • 将每一个功能,单独定义成一个类文件;
  • 每一个类文件,尽量以”.class.php”结尾;例如:test.class.php
  • 类文件的主名,要与类名一致;例如:class test{}

test.class.php

<?php
class test{
    public function __construct(){
        echo "test class";
    }
}

demo.php

<?php
function __autoload($classname){
    // 构造类文件的路劲(这边是在本地)
    $filename = "$classname.class.php";
    // 如果类文件存在,则包含
    if(file_exists($filename)) require_once($filename);
}
$t = new test();      // 输出 test class
?>

自定义类文件加载函数

  • __autoload()有点局限性,如果类文件位于不同的目录,类文件名命名方式也不尽相同
  • 自定义类文件加载函数:spl_autoload_register(),主要应用在项目中,可以应对不同的情况
  • 每个函数就是一种类文件的加载规则。
<?php
// 自定义类文件加载函数spl_autoload_register()语法格式
// 参数:是函数,有两种情况
// 1. 参数是字符串的函数名称,函数传地址
// 2. 参数也可以是匿名函数,函数传地址

spl_autoload_register('test1');
spl_autoload_register('test2');

function test1($classname){
    //构建类文件路径
    $filename = "./libs/$classname.class.php";
    //如果类文件存在,则包含
    if(file_exists($filename)) require_once($filename);
}

function test2($classname){
    //构建类文件路径
    $filename = "./include/$classname.class.php";
    //如果类文件存在,则包含
    if(file_exists($filename)) require_once($filename);
}
?>

对象克隆

  • 创建新对象有几种方式:

    • 1.使用 new 关键字
    • 2.使用 clone 关键字
  • $obj2 = $obj1 是创建新对象吗?将$obj1 的地址复制给$obj2,$obj1 和$obj2 指向同一份数据。是同一个对象
<?php
class test{}
$obj1 = new test();

// 这里是引用传递
$obj2 = $obj1;
var_dump($obj1,$obj2);     // object(test)#1 (0) { } object(test)#1 (0) { }
?>

克隆举例:

<?
class A{
    private $name = 'a';

    // 当对象克隆完成时,魔术方法 __clone()自动调用
    public function __clone(){
        $this->name = 'b';
    }
}
$a = new A();
$b = clone $a;
var_dump($a);
echo '<br>';
var_dump($b);

代码输出:

object(A)#1 (1) { ["name":"A":private]=> string(1) "a" }
object(A)#2 (1) { ["name":"A":private]=> string(1) "b" }

对象遍历

在类内可以遍历所有对象属性,

在类外只能遍历公共对象属性

<?php
class test{
    private $name = 'taoy';
    private $age = 19;
    public $score = 100;

    public function ShowAll(){
        foreach($this as $k=>$v){
                echo __class__."->{$k}--->$v".'<br />';
        }
    }
}

$t = new test();

// 在类外访问
foreach($t as $k=>$v){
    echo "{$k}--->{$v}".'<br />';
}
echo '<hr>';
// 在类内访问
$t->ShowAll();

代码输出:

score--->100
--------------------------
test->name--->taoy
test->age--->19
test->score--->100

魔术方法

  • __construct 具有构造函数的类会在每次创建新对象时先调用此方法;初始化工作执行
  • __desstruct 对象的所有引用都被删除或者当对象被显式销毁时执行
  • __call() 在对象中调用一个不可访问方法时,__call() 会被调用。
  • __callStatic()在静态上下文中调用一个不可访问方法时,__callStatic() 会被调用
  • __toString()当一个类的实例对象;被当成一个字符串输出时调用
  • __set() 在给不可访问的属性赋值时调用
  • __get() 读取不可访问的属性值时自动调用
  • __isset() 当对不可访问的私有属性使用isset或empty时; 自动调用
  • __unset() 当对不可访问的私有属性使用unset时;自动调用
  • __invoke() 当把对象当成函数调用时,自动调用
<?php

class A{
    public function __call($func, $args){
        echo "<br> {$func} func not exitst";
    }
    public function __toString(){
        return "<br>string";
    }
    public function __invoke(){
        echo "<br>invoke";
    }
}

$a = new A();
echo $a;     // 调用 __toString()
$a();        // 调用 __invoke()
$a->hhh();     // 不存在次方法, 调用__call()

代码输出

string
invoke
hhh func not exitst

重载

PHP 魔术方法

  • PHP 所提供的"重载"(overloading)是指动态地"创建"类属性和方法。我们是通过魔术方法来实现的
  • 所有的重载方法都必须被声明为 public
  • 这些魔术方法的参数都不能通过引用传递

__set()

  • 描述:在给不可访问属性赋值时,__set()会被调用
  • 语法:public void __set(string $name,mixed $value)
<?php
class test{
    private $name;

    public function __set($name, $v){
        $this->$name = $v;
    }
}
$t = new test();
// 给不可访问的属性赋值
$t->name = 'test';
var_dump($t); //    object(test)#1 (1) { ["name":"test":private]=> string(4) "test" }

__get()

  • 描述:读取不可访问属性的值, __get()会被调用
  • 语法:public mixed __get(string $name)
<?php
class test{
    private $name = 'a';

    public function __get($name){
        return $this->$name;
    }
}
$t = new test();
echo "my name is {$t->name}";     //    my name is a

__isset()

  • 描述:当对不可访问的私有属性使用isset或empty时; 自动调用
  • 语法:public void __isset(string $name)
<?php
header("Content-Type: text/html;charset=utf-8");

class test{
    private $name = 'a';

    public function __isset($name){
        echo "不能对变量{$name}私有属性使用isset()或empty()";
    }
}
$t = new test();
isset($t->name);    // 不能对变量name私有属性使用isset()或empty()
?>

__unset()

  • 描述:当对不可访问属性调用 unset() 时,__unset()会被调用
  • 语法:public void __unset ( string $name )

__call()

  • 描述:在对象中调用一个不可访问方法时,__call() 会被调用
  • 语法:public mixed __call ( string $name , array $arguments )

__callStatic()

  • 描述:用静态方法中调用一个不可访问的方法时, __callStatic()会被调用
  • 语法:public static mixed __callStatic(string $name,array $arguments)

instanceof关键字

  • 描述:判断一个对象是不是某个类产生的对象
  • 语法:$obj instanceof ClassName
  • 返回值:如果$obj ClassName的对象,则返回TRUE,否则,返回FALSE

静态延迟绑定

自 PHP 5.3.0 起,PHP 增加了一个叫做后期静态绑定的功能,用于在继承范围内引用静态调用的类。
"后期绑定"的意思是说,static::不再被解析为定义当前方法所在的类,而是在实际运行时计算的。也可以称之为"静态绑定",因为它可以用于(但不限于)静态方法的调用

  • 语法:static::静态属性,静态方法,成员方法,类常量
<?php
header("Content-Type: text/html;charset=utf-8");

class A{
    protected static $name = 'a';
    const TITLE = 'A';
    // 如果只有一个类,self和static都代表当前类
    function showinfo(){
        echo "Title: ".static::TITLE;
        echo "<br>NAME: ".self::$name;
        echo "<br> NAME:".static::$name;
    }
}
$a = new A();
$a->showinfo();
?>

输出结果:

Title: A
NAME: a
NAME:a

类型约束

PHP 类型约束

常用的魔术常量

__LINE__,当前行号
__FILE__,当前文件名
__DIR__,当前目录名
__FUNCTION__,当前函数名
__CLASS__,当前类名
__METHOD__,当前方法
__NAMESPACE__,当前空间名(在 PDO 中讲)

本文链接:

https://www.betao.cn/archives/phpreview06.html
1 + 3 =
快来做第一个评论的人吧~