From 3489413661edc79b6a728a9fd5e595cefd62a9c3 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Thu, 23 Apr 2026 14:41:24 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=B7=BB=E5=8A=A0=20AOT=20=E7=BC=96?= =?UTF-8?q?=E8=AF=91=E5=99=A8=E7=B1=BB=E7=BB=A7=E6=89=BF=E8=A7=84=E5=88=99?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E5=92=8C=E9=A2=84=E8=A7=88=E7=89=88=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E9=A1=BB=E7=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 CLASS_INHERITANCE.md 文档,详细说明 AOT 编译器类继承规则 - 新增 README.md 文件,包含预览版使用条款和责任限制说明 - 文档涵盖合法继承示例、非法继承示例和最佳实践指南 - 添加故障排除部分和常见问题解答 - 说明 AOT 编译器与传统 PHP 在继承方面的差异对比 - 强调预览版软件的使用限制和风险提示 --- README.md | 53 ++++ docs/CLASS_INHERITANCE.md | 570 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 623 insertions(+) create mode 100644 README.md create mode 100644 docs/CLASS_INHERITANCE.md diff --git a/README.md b/README.md new file mode 100644 index 00000000..cf77a9e1 --- /dev/null +++ b/README.md @@ -0,0 +1,53 @@ +## Swoole-Compiler Native AOT 编译器预览版使用须知 + +**请在使用本软件前仔细阅读以下条款:** + +### 一、软件状态说明 + +1. 当前版本为 **预览版(Preview Version)**,仅供测试、评估和学习使用 +2. 本版本可能存在未知的缺陷(BUG)、功能不完善、性能不稳定等问题 +3. 软件的功能、API 接口、编译行为等可能在后续版本中发生重大变更,恕不另行通知 + +### 二、使用限制 + +**严禁将预览版用于以下场景:** + +- ❌ 生产环境(Production Environment) +- ❌ 商业项目的正式部署 +- ❌ 关键业务系统 +- ❌ 涉及用户数据安全的应用 +- ❌ 任何对稳定性、可靠性有严格要求的场景 + +**建议使用场景:** + +- ✅ 本地开发测试 +- ✅ 技术评估与验证 +- ✅ 性能基准测试 +- ✅ 学习研究目的 + +### 三、责任限制 + +1. **使用风险自负** - 用户明确知晓并接受使用预览版软件可能带来的所有风险 +2. **无质量保证** - 开发团队不对软件的适用性、稳定性、安全性做任何明示或暗示的保证 +3. **后果自行承担** - 因使用本软件导致的任何直接或间接损失,包括但不限于: + - 数据丢失或损坏 + - 业务中断或服务不可用 + - 经济损失 + - 安全漏洞或数据泄露 + - 第三方索赔 + + **均由用户自行承担全部责任**,开发团队不承担任何法律责任或赔偿义务 + +4. **技术支持** - 预览版仅提供有限的社区支持,不保证问题响应时间和解决方案 + +### 四、知识产权 + +本软件的所有知识产权归 Swoole 开发团队所有。未经授权,不得用于商业用途或进行逆向工程。 + +### 五、条款接受 + +**下载、安装或使用本软件即表示您已完全理解并接受本免责声明的全部条款。如不同意,请立即停止使用并删除软件。** + +--- + +> ⚠️ **重要提示:** 正式稳定版发布前,请持续关注官方公告。我们将在软件达到生产就绪标准后正式发布 GA(General Availability)版本。 \ No newline at end of file diff --git a/docs/CLASS_INHERITANCE.md b/docs/CLASS_INHERITANCE.md new file mode 100644 index 00000000..2de6368f --- /dev/null +++ b/docs/CLASS_INHERITANCE.md @@ -0,0 +1,570 @@ +# AOT 编译器类继承规则 + +## 📋 概述 + +AOT(Ahead-Of-Time)编译器在编译阶段会对类的继承关系进行严格检查。与传统的 PHP 运行时检查不同,AOT 编译器要求在**编译期**就能确定所有父类和接口的存在性。 + +--- + +## ⚠️ 核心规则 + +### 规则一:只能继承已存在的类 + +```php +// ✅ 正确:继承 PHP 内置类 +class MyException extends Exception {} + +// ✅ 正确:继承同一项目中定义的类 +class BaseClass {} +class ChildClass extends BaseClass {} + +// ❌ 错误:继承不存在的类 +class MyClass extends NonExistentClass {} +// 编译错误:Class `MyClass` inherits from a non-existent class `NonExistentClass` +``` + +### 规则二:不能继承 autoload 运行时载入的类 + +```php +// ❌ 错误:依赖 autoload 的类 +class MyClass extends ExternalLibrary\BaseClass {} +// 如果 BaseClass 需要通过 autoload 在运行时加载,编译将失败 + +// ✅ 正确:使用接口代替 +interface BaseInterface {} +class MyClass implements BaseInterface {} +``` + +### 规则三:不能继承内部类(Internal Class) + +```php +// ❌ 错误:继承 PHP 内部类 +class MyArray extends ArrayObject {} +// 编译错误:Class `MyArray` Cannot inherit built-in class `ArrayObject` + +// ✅ 正确:使用组合模式 +class MyContainer { + private ArrayObject $storage; + + public function __construct() { + $this->storage = new ArrayObject(); + } +} +``` + +--- + +## 🔍 编译期检查机制 + +### 检查流程 + +1. **词法分析阶段** + - 解析 `extends` 和 `implements` 关键字 + - 提取父类和接口的名称 + +2. **符号表构建** + - 收集当前文件中所有已定义的类 + - 查询 PHP 内置类列表 + - 验证继承关系的合法性 + +3. **错误报告** + - 发现非法继承时立即报错 + - 提供详细的错误位置和原因 + +### 检查代码位置 + +相关实现在 `src/Php/Translator.php`: + +```php +if ($extends) { + $parentClass = $this->getParentClass($class->extends); + if ($this->hasNativeClass($parentClass)) { + // 父类是已定义的 native 类 + $parent = $this->getClassDef($parentClass); + if ($parent->flags & Modifiers::FINAL) { + $this->fatalError($class, "Class `{$this->class}` cannot extend final class `{$parentClass}`"); + } + $this->classDef->extends = $parentClass; + } else { + // 检查是否为 PHP 内部类 + if (Reflection::isInternalClass($parentClass)) { + $this->fatalError($class, "Class `{$this->class}` Cannot inherit built-in class `$parentClass`"); + } else { + $this->fatalError($class, "Class `{$this->class}` inherits from a non-existent class `$parentClass`"); + } + } +} +``` + +--- + +## 🎯 合法继承示例 + +### 示例一:继承项目内定义的类 + +```php +area; + } +} + +// 继承基类(✅ 允许) +class Circle extends Shape { + private float $radius; + + public function __construct(float $radius) { + $this->radius = $radius; + } + + public function calculateArea(): float { + $this->area = M_PI * $this->radius ** 2; + return $this->area; + } +} + +function main() { + $circle = new Circle(5); + echo "Circle area: " . $circle->getArea() . "\n"; +} +``` + +### 示例二:实现接口 + +```php +name = $name; + $this->price = $price; + } + + public function render(): string { + return "
{$this->name} - \${$this->price}
"; + } + + public function serialize(): string { + return json_encode(['name' => $this->name, 'price' => $this->price]); + } +} + +function main() { + $product = new Product('Widget', 19.99); + echo $product->render() . "\n"; + echo $product->serialize() . "\n"; +} +``` + +### 示例三:多层继承 + +```php +data[$key] = $value; + } + + abstract public function execute(): void; +} + +// 抽象的用户控制器 +abstract class UserController extends Controller { + protected ?string $userId = null; + + public function setUserId(string $id): void { + $this->userId = $id; + } +} + +// 具体的用户列表控制器(✅ 允许) +class UserListController extends UserController { + private array $users = []; + + public function execute(): void { + echo "User List for ID: {$this->userId}\n"; + foreach ($this->users as $user) { + echo " - {$user}\n"; + } + } +} + +function main() { + $controller = new UserListController(); + $controller->setUserId('123'); + $controller->execute(); +} +``` + +--- + +## ❌ 非法继承示例 + +### 示例一:继承不存在的类 + +```php + +``` + +**编译错误**: +``` +Fatal error: Class `MyClass` inherits from a non-existent class `NonExistentBase` +in /path/to/file.php on line X +``` + +**解决方案**: +```php + +``` + +**编译错误**: +``` +Fatal error: Class `MyService` inherits from a non-existent class `ExternalLib\BaseClass` +in /path/to/file.php on line X +``` + +**解决方案**: + +**方案 A - 使用接口**: +```php +base = new BaseClass(); + } + + public function process(): mixed { + return $this->base->doSomething(); + } +} +``` + +### 示例三:继承 PHP 内部类 + +```php + +``` + +**编译错误**: +``` +Fatal error: Class `MyDatabase` Cannot inherit built-in class `PDO` +in /path/to/file.php on line X +``` + +**解决方案**: +```php +connection = new PDO($dsn); + } + + public function query(string $sql): array { + return $this->connection->query($sql)->fetchAll(); + } +} +``` + +--- + +## 💡 最佳实践 + +### 1. 优先使用接口而非继承 + +```php +// ❌ 不推荐:深度继承链 +class A {} +class B extends A {} +class C extends B {} +class D extends C {} + +// ✅ 推荐:使用接口 +interface ServiceInterface {} +class UserService implements ServiceInterface {} +class ProductService implements ServiceInterface {} +``` + +### 2. 使用组合代替继承 + +```php +// ❌ 不推荐:继承内部类 +class MyCollection extends ArrayCollection { + // ... +} + +// ✅ 推荐:组合模式 +class Collection { + private ArrayCollection $items; + + public function __construct() { + $this->items = new ArrayCollection(); + } + + public function add(mixed $item): void { + $this->items->add($item); + } +} +``` + +### 3. 在项目内定义可继承的基类 + +```php +middleware('auth'); + echo "Handling user request\n"; + } +} + +function main() { + $controller = new UserController(); + $controller->handle(); +} +``` + +### 4. 避免循环依赖 + +```php +// ❌ 错误:循环继承会导致编译失败 +// file1.php +class A extends B {} + +// file2.php +class B extends A {} + +// ✅ 正确:单向继承 +// base.php +class Base {} + +// child.php +class Child extends Base {} +``` + +--- + +## 🔧 故障排除 + +### 问题一:编译时报 "non-existent class" + +**症状**: +``` +Fatal error: Class `MyClass` inherits from a non-existent class `ParentClass` +``` + +**诊断步骤**: +1. 检查 `ParentClass` 是否在编译单元中定义 +2. 确认没有拼写错误 +3. 验证类的命名空间是否正确 + +**解决方案**: +```php +// 确保父类在子类之前定义或在同一文件中 +class ParentClass {} +class MyClass extends ParentClass {} +``` + +### 问题二:无法使用第三方库的类作为父类 + +**症状**: +需要使用外部库的功能,但不能直接继承 + +**解决方案**: + +**方法 A - 适配器模式**: +```php +class ExternalAdapter { + private ExternalClass $external; + + public function __construct() { + $this->external = new ExternalClass(); + } + + public function doWork(): mixed { + return $this->external->execute(); + } +} +``` + +**方法 B - 委托模式**: +```php +class Wrapper { + public function __call(string $name, array $args): mixed { + $external = new ExternalClass(); + return call_user_func_array([$external, $name], $args); + } +} +``` + +### 问题三:需要扩展 PHP 内置功能 + +**症状**: +想要增强或修改 PHP 内置类的行为 + +**解决方案**: + +**使用装饰器模式**: +```php +class EnhancedStorage { + private ArrayObject $storage; + + public function __construct() { + $this->storage = new ArrayObject(); + } + + public function set(string $key, mixed $value): void { + echo "Setting {$key}\n"; + $this->storage[$key] = $value; + } + + public function get(string $key): mixed { + echo "Getting {$key}\n"; + return $this->storage[$key] ?? null; + } +} +``` + +--- + +## 📊 对比:AOT vs 传统 PHP + +| 特性 | AOT 编译器 | 传统 PHP | +|------|-----------|----------| +| **检查时机** | 编译期 | 运行时 | +| **错误发现** | 编译时立即报错 | 执行到代码时才报错 | +| **autoload 支持** | ❌ 不支持作为父类 | ✅ 完全支持 | +| **继承内部类** | ❌ 禁止 | ✅ 允许(部分) | +| **性能影响** | 无运行时开销 | 有运行时检查开销 | + +--- + +## 📚 相关资源 + +- **类型系统**: [NATIVE_TYPES.md](NATIVE_TYPES.md) +- **语法限制**: [UNSUPPORTED_SYNTAX.md](UNSUPPORTED_SYNTAX.md) +- **编译模式**: [COMPILATION_MODES.md](COMPILATION_MODES.md) +- **快速入门**: [QUICKSTART.md](QUICKSTART.md) + +--- + +## ❓ 常见问题 + +### Q: 为什么 AOT 编译器不允许继承 autoload 类? + +A: AOT 编译器在编译阶段就需要知道所有类的完整结构。autoload 是在运行时触发的机制,编译期无法获取类的定义信息,因此无法生成正确的 C++ 代码。 + +### Q: 如何判断一个类是否是内部类? + +A: AOT 编译器使用 `Reflection::isInternalClass()` 函数来判断。该函数会扫描所有已声明的类,并使用 `ReflectionClass::isInternal()` 方法检测。 + +### Q: 可以实现接口吗? + +A: ✅ 可以!AOT 编译器完全支持实现接口。接口只定义方法签名,不涉及具体实现,因此可以在编译期验证。 + +### Q: trait 可以使用吗? + +A: Trait 的使用同样受到限制。Trait 必须在编译期可见,不能依赖 autoload 动态加载。 + +--- + +**最后更新**: 2024 年 3 月 20 日 +**适用版本**: PHP AOT Compiler v1.x