🌟 匿名类(Anonymous Class)------"一次性用完就扔的小纸条"
一、什么是匿名类?------没有名字的"临时工"
想象你去便利店买水:
- 正常情况下,你要用"微信支付"或"支付宝"------它们是有名字的支付方式 (就像一个正式类
class WeChatPay
)。 - 但有时候你没带手机,店员说:"你写张纸条,写上'我叫小明,欠10块钱',我收了就行。"
- 这张"手写欠条"就是没有名字的,只用一次,用完就扔。
👉 这张"手写欠条"就是匿名类:它是一个"对象",但没有正式的名字,只用一次,适合临时任务。
✅ 二、如何创建一个匿名类?------基本语法
🔹 最简单的匿名类
php
$obj = new class {
public function hello() {
echo "你好,我是匿名类!\n";
}
};
$obj->hello(); // 输出:你好,我是匿名类!
📌 关键点:
new class
是关键词,意思是"新建一个没有名字的类"- 大括号
{}
里面可以写方法、属性 - 立刻创建了一个对象,可以直接使用
- php>7.0
🔧 三、让匿名类更强大------它不是"残废"的!
虽然匿名类没有名字,但它功能完整,支持:
1. ✅ 传参数(有构造函数)
php
$name = '小红';
$obj = new class($name) {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function greet() {
echo "你好,我是{$this->name}!\n";
}
};
$obj->greet(); // 输出:你好,我是小红!
📌 小贴士:括号里的 $name
会传给 __construct
2. ✅ 继承父类(extends)
php
class Animal {
protected function speak($sound) {
echo $sound . "\n";
}
}
$obj = new class extends Animal {
public function bark() {
$this->speak("汪汪!"); // 可以调用父类方法
}
};
$obj->bark(); // 输出:汪汪!
✅ 匿名类也可以"继承"其他类。
3. ✅ 实现接口(implements)
php
interface Logger {
public function log($msg);
}
$logger = new class implements Logger {
public function log($msg) {
echo "[LOG] " . $msg . "\n";
}
};
$logger->log("系统启动"); // 输出:[LOG] 系统启动
✅ 这是匿名类最常见的用途:临时实现一个接口,比如设置日志器、事件处理器等。
4. ✅ 使用 Trait
php
trait SayHello {
public function hello() {
echo "Hello!\n";
}
}
$obj = new class {
use SayHello;
};
$obj->hello(); // 输出:Hello!
✅ 匿名类也可以"借用" Trait 的方法。
🔐 四、匿名类访问外部类?------"外层的秘密我能知道吗?"
假设匿名类写在一个类里面:
php
class User {
private $id = 123;
protected $name = '张三';
public function getAnonymous() {
return new class {
// 这里能访问 $this->id 吗?❌ 不能!
};
}
}
❌ 不能直接访问 private
或 protected
成员
匿名类不能直接访问外层类的私有或受保护属性/方法。
✅ 正确做法:通过构造器传进来
php
class User {
private $id = 123;
public function getAnonymous() {
// 把外层的私有属性传进去
return new class($this->id) {
private $id;
public function __construct($id) {
$this->id = $id;
}
public function showId() {
echo "我的ID是:{$this->id}\n";
}
};
}
}
$user = new User();
$obj = $user->getAnonymous();
$obj->showId(); // 输出:我的ID是:123
📌 总结:
private
属性:必须通过构造器传进来protected
方法:可以让匿名类extends 外层类
来访问
🔁 五、多次创建,是同一个类吗?
scss
function create() {
return new class {};
}
$a = create();
$b = create();
var_dump(get_class($a) === get_class($b)); // ✅ 输出:true
✅ 虽然名字是系统生成的(如 class@anonymous#1
),但只要结构相同,PHP 认为它们是同一个类型。
🆕 六、PHP 8.3 新特性:只读匿名类
php
$person = new readonly class('小明', 20) {
public function __construct(
private string $name,
private int $age
) {}
public function introduce() {
echo "我是{$this->name},今年{$this->age}岁。\n";
}
};
$person->introduce(); // 输出:我是小明,今年20岁。
// $person->name = '小红'; ❌ 错误!只读类不能修改属性
✅ 适合创建"不可变对象",防止意外修改。
🧩 七、匿名类的典型使用场景
场景 | 示例 |
---|---|
临时实现接口 | setLogger(new class implements Logger) |
单元测试 mock | new class { public function query() { return []; } } |
一次性回调 | on('login', new class { public function handle() { ... } }) |
快速配置对象 | new class($config) { ... } |
🚫 匿名类的限制(不能做的事)
不能做的事 | 说明 |
---|---|
不能序列化 | 因为没有名字,无法反序列化 |
不能用 class_exists() 判断 |
它不是"正式类" |
不要依赖类名 | 名字是系统生成的,如 class@anonymous#1 ,不要在代码中判断 |
✅ 总结:创建匿名类的完整步骤
- 写
new class
- 可选:传参数 →
new class($arg)
- 可选:继承类 →
extends ParentClass
- 可选:实现接口 →
implements Interface
- 写
{}
,在里面写属性和方法 - 可选:使用 Trait →
use SomeTrait;
- 写构造函数接收参数
- 创建对象并使用
📚 复习口诀(背下来!)
arduino
new class 不取名,
一次使用最轻盈。
参数构造能接收,
继承实现都可行。
private 要靠传进来,
protected 可继承。
只读 8.3 才支持,
临时对象它最灵!