《PHP类的基础概念:从零开始学面向对象》

《PHP类的基础概念:从零开始学面向对象》

什么是"类"?------ 你的设计图纸

想象你要开一家机器人制造工厂。你需要一张"设计图纸",上面画着机器人该有什么"部件"(比如名字、型号)和"功能"(比如行走、说话)。在 PHP 里, "类"(Class)就是这张设计图纸

kotlin 复制代码
// Robot 类:机器人设计图纸
class Robot {
    // ... 在这里定义部件和功能
}

类本身不是机器人,它是制造机器人的模板

类里有什么?------ 你的三大法宝

一张完整的图纸包含三样东西:

  1. 常量 (Constants)固定不变的设定。

    • const MAX_SPEED = 100; // 所有机器人的最高速度上限
    • 一旦定义,永远不能改变。
  2. 属性 (Properties) :机器人的"部件 "或"特征"。

    • public $name; // 机器人的名字
    • public $color; // 机器人的颜色
    • 属性是机器人的"身份证信息"。
  3. 方法 (Methods) :机器人的"功能 "或"动作"。

    • public function walk() { ... } // 机器人走路的功能
    • public function speak($words) { ... } // 机器人说话的功能
    • 方法是机器人的"技能包"。

📌 重要提示 :在方法内部定义的变量(如 function walk() { $step = 1; } 中的 $step)是局部变量 ,只在该方法执行时存在,用完就消失,它不是类结构的一部分。

创建机器人(实例化)------ 用图纸造机器

有了图纸,就可以造机器人了!这叫"实例化 "。使用 new 关键字。

ini 复制代码
$myRobot = new Robot(); // 造一个机器人

$myRobot 就是根据 Robot 类创造出来的具体机器人 ,我们称之为"对象 "或"实例"。

new 操作符的进化:PHP 8.0+ 的任意表达式支持

在 PHP 8.0 之前,new 后面只能跟固定的类名

ini 复制代码
// PHP 8.0 之前
$className = 'Robot';
$instance = new $className(); // 需要变量,写法稍显别扭

从 PHP 8.0.0 起,new 可以用在任意表达式中,这带来了巨大的灵活性和简洁性!

php 复制代码
// ✅ PHP 8.0+ 新写法:直接在表达式中使用 new

// 1. 从函数返回类名
function getRobotClass(): string {
    return 'Robot';
}
$robot1 = new (getRobotClass());

// 2. 字符串拼接
$robot2 = new ('Rob' . 'ot');

// 3. 使用 ::class 常量
class AdvancedRobot {}
$robot3 = new (AdvancedRobot::class);

// 4. 创建后立即调用方法
echo (new DateTime())->format('Y-m-d'); // 创建 DateTime 对象并调用 format
// 注意:从 PHP 8.4 起,括号 ( ) 可以省略:echo new DateTime()->format('Y-m-d');

💡 关键点

  • new ($className) 这种写法在 PHP 8.1+ 被标记为"软弃用",强烈推荐使用 new ($expression) 的新语法
  • 给构造函数传参 :如果类有构造函数需要参数,直接在表达式后的括号里传入即可:new (<expression>)(<arg1>, <arg2>)
php 复制代码
// 假设 Robot 构造函数需要 name 和 age
class Robot {
    public function __construct(string $name, int $age) { ... }
}
// 正确传参方式
$robot = new ('Rob' . 'ot')('小助手', 5);

对象的"引用"特性 ------ 一个机器人,多个遥控器

记住核心规则:对象变量默认是"引用" ,而不是"值"。

ini 复制代码
$robot1 = new Robot();
$robot2 = $robot1; // $robot2 不是新机器人,而是指向 $robot1 的"遥控器"

$robot2->name = "小助手"; // 通过 $robot2 的遥控器改名字

echo $robot1->name; // 输出:小助手 ❗

为什么? 因为 $robot1$robot2 指向的是同一个机器人实体。改一个,另一个也跟着变。

继承:机器人升级 ------ extends

PHP 支持"机器人升级"。新机器人可以继承旧机器人的所有部件和功能,然后添加自己的新东西。

scala 复制代码
class SuperRobot extends Robot { // SuperRobot 继承 Robot
    public $laser; // 新增激光武器

    public function fly() { // 新增飞行功能
        echo "起飞!";
    }
}
  • extends 表示继承。
  • 重要限制 :PHP 不支持多重继承,一个机器人只能有一个"爸爸"(基类)。
覆盖 (Override) 与 Final

新机器人可以改进旧功能。

scala 复制代码
class SuperRobot extends Robot {
    // 覆盖父类的 speak 方法
    public function speak($words) {
        echo "超级机器人说:" . $words;
    }
}
  • 覆盖规则 (LSP - 里氏替换原则)

    • 方法签名(参数)必须兼容。不能删除父类方法的必需参数。
    • 可以增加可选参数。
    • 不能收紧访问权限(比如父类 public,子类不能改成 private)。
  • 覆盖的例外

    • 构造函数 (__construct) :子类构造函数的签名不需要 与父类兼容。子类可以有自己独立的参数列表(但仍需通过 parent::__construct() 调用父类构造函数来初始化父类部分)。
    • private 方法 :子类可以定义一个与父类 private 方法同名的方法,但这不是覆盖 ,而是完全独立的方法 ,因为 private 方法在子类中不可见。
  • Final 关键字 :如果父类方法或常量被标记为 final,子类绝对不能覆盖它,这是"最终设定"。

::class ------ 获取类的全名

需要知道一个类的完整名称(尤其带命名空间时)?用 ::class

php 复制代码
namespace Factory\Robots;

class WorkerRobot {}

echo WorkerRobot::class; // 输出: Factory\Robots\WorkerRobot

// 对象也可以用 (PHP 8.0+)
$robot = new WorkerRobot();
echo $robot::class; // 输出: Factory\Robots\WorkerRobot

Nullsafe 操作符 ?-> ------ 安全调用

不确定机器人是否存在或有某个功能?用 ?-> 安全调用。

ini 复制代码
// 自 PHP 8.0.0 起可用  
$result = $repository?->getUser(5)?->name;  
  
// 上边那行代码等价于以下代码  
if (is_null($repository)) {  
$result = null;  
} else {  
$user = $repository->getUser(5);  
if (is_null($user)) {  
$result = null;  
} else {  
$result = $user->name;  
}  
}
相关推荐
JohnYan9 分钟前
工作笔记 - NATS的Nkey认证
javascript·后端·rabbitmq
guojl36 分钟前
MyBatis插件机制
后端
SimonKing37 分钟前
营销级二维码生成术:Java如何打造专属标识
java·后端·程序员
_风不会停息41 分钟前
JDK21 虚拟线程的实现原理和应用
java·后端
菜鸟的迷茫43 分钟前
分布式唯一 ID 生成方案对比(Snowflake、Leaf、Redis、数据库自增)
后端
小塔猫1 小时前
RabbitMQ相关信息及使用指南
后端
f0rb1 小时前
Java ORM 代码量和性能对比:DoytoQuery vs SpringDataJPA/SpringJdbc/jOOQ/MyBatis-plus
后端·orm
用户9096783069431 小时前
python 判断字符串是否是回文(例如:abba)
后端
开始学java1 小时前
包机制(package、import)
后端
ArabySide1 小时前
【ASP.NET Core】探讨注入EF Core的DbContext在HTTP请求中的生命周期
后端·http·asp.net·asp.net core·efcore