抽象类不能被实例化,因此不存在“抽象类对象转数组”;实际可转数组的是其具体子类的实例,常用方式包括强制类型转换、get_object_vars()和自定义toArray()方法。

PHP 中抽象类本身不能被实例化,所以不存在“抽象类对象转数组”这种操作。真正能转数组的,是继承了抽象类的具体子类的实例。关键不在“抽象类”,而在“对象序列化为数组”的通用机制。
为什么抽象类对象不能直接转数组?
抽象类是设计层面的约束,用于定义公共接口和部分实现,它禁止被 new 出来。运行时根本不存在“抽象类对象”,只有它的子类实例。试图写 new AbstractClass() 会直接报 Fatal error: Cannot instantiate abstract class。
子类实例转数组的 3 种常用方式
假设你有如下结构:
abstract class Animal {
protected $name;
protected $age;
abstract public function speak();
}
class Dog extends Animal {
private $breed;
public function __construct($name, $age, $breed) {
$this->name = $name;
$this->age = $age;
$this->breed = $breed;
}
public function speak() { return 'Woof!'; }
}
对 $dog = new Dog('Leo', 3, 'Golden'); 转数组,可选方法:
立即学习“PHP免费学习笔记(深入)”;
-
强制类型转换
(array)$obj:最简单,但只导出 public 属性(protected/private 会变成特殊键名,如"\0*\0name"),且不触发任何逻辑。 -
使用
get_object_vars():仅返回 当前作用域可见的 public 属性(在类内部调用能看到 protected,但在外部调用只返回 public)。 -
自定义
toArray()方法(推荐):在抽象类中声明抽象或默认方法,由子类实现或继承,可精确控制字段、过滤敏感数据、格式化日期等。
实战:在抽象类中统一定义 toArray() 行为
这是最健壮、可维护的方式:
abstract class Animal {
protected $name;
protected $age;
protected $createdAt;
public function __construct($name, $age) {
$this->name = $name;
$this->age = $age;
$this->createdAt = new DateTime();
}
// 提供默认实现:导出所有 protected/public 非方法属性
public function toArray(): array {
$arr = [];
$reflection = new ReflectionObject($this);
foreach ($reflection->getProperties(ReflectionProperty::IS_PROTECTED | ReflectionProperty::IS_PUBLIC) as $prop) {
$prop->setAccessible(true);
$arr[$prop->getName()] = $prop->getValue($this);
}
return $arr;
}
abstract public function speak();
}
class Dog extends Animal {
private $breed;
public function __construct($name, $age, $breed) {
parent::__construct($name, $age);
$this->breed = $breed;
}
public function speak() { return 'Woof!'; }
// 可选择重写 toArray(),加入 breed 或隐藏 createdAt
public function toArray(): array {
$arr = parent::toArray();
$arr['breed'] = $this->breed;
unset($arr['createdAt']); // 敏感或冗余字段可剔除
return $arr;
}
}
// 使用
$dog = new Dog('Leo', 3, 'Golden');
var_dump($dog->toArray());
// 输出:['name' => 'Leo', 'age' => 3, 'breed' => 'Golden']
注意事项与避坑点
-
(array)和get_object_vars()都无法访问private属性(即使在本类中);反射是唯一可靠途径。 - 若属性是对象(如 DateTime)、资源或闭包,直接转数组会丢失行为,需在
toArray()中手动处理(例如$date->format('Y-m-d'))。 - 避免在
toArray()中调用可能引发副作用的方法(如修改状态、查库),它应是纯数据导出。 - 如需 JSON 输出,直接
json_encode($obj)会自动调用对象的JsonSerializable接口 —— 可让抽象类实现该接口,统一控制 JSON 行为。



















