PHP OOP中如何让属性仅接受指定格式的关联数组
确保MarketStall类$products属性的类型约束
原有代码
Product类
class Product { private $name; private $price; private $sellingByKg; public function __construct($name = null, $price = null, $sellingByKg = null) { $this->name = $name; $this->price = $price; $this->sellingByKg = $sellingByKg; } public function getName() { return $this->name; } public function getPrice() { return $this->price; } public function getSellingByKg() { return $this->sellingByKg; } }
原有MarketStall类
class MarketStall extends Product { public $products; public function __construct( $products= [], $name = null, $price = null, $sellingByKg = null ) { parent::__construct($name, $price, $products); $this->products = $products; } }
需求
确保MarketStall类的$products属性仅接受关联数组,该数组的键为产品名称(字符串类型),值为Product类的实例对象。
修改后的MarketStall类
class MarketStall extends Product { // 改为私有属性,避免外部直接赋值绕过验证 private array $products = []; public function __construct( array $products = [], $name = null, $price = null, $sellingByKg = null ) { // 修正父类构造函数的参数错误:原代码将$products误传给了$sellingByKg参数 parent::__construct($name, $price, $sellingByKg); // 验证并设置products $this->setProducts($products); } /** * 设置products数组,验证每个键值对是否符合要求 * @param array $products * @throws InvalidArgumentException */ public function setProducts(array $products): void { $validatedProducts = []; foreach ($products as $productName => $product) { // 验证键是否为字符串类型(产品名称) if (!is_string($productName)) { throw new InvalidArgumentException('产品数组的键必须是字符串类型的产品名称'); } // 验证值是否为Product实例 if (!$product instanceof Product) { throw new InvalidArgumentException(sprintf('产品"%s"必须是Product类的实例', $productName)); } // 可选:确保产品实例的名称和数组键一致,避免数据不一致 if ($product->getName() !== $productName) { throw new InvalidArgumentException(sprintf('产品数组键"%s"与产品实例名称"%s"不匹配', $productName, $product->getName())); } $validatedProducts[$productName] = $product; } $this->products = $validatedProducts; } /** * 获取products数组 * @return array */ public function getProducts(): array { return $this->products; } // 可选:添加单个产品的添加方法 public function addProduct(Product $product): void { $productName = $product->getName(); if ($productName === null) { throw new InvalidArgumentException('产品必须设置名称才能添加到MarketStall'); } $this->products[$productName] = $product; } }
关键修改说明
- 属性私有化:将
$products改为私有属性,强制通过setProducts或addProduct方法修改,避免外部直接赋值跳过验证逻辑。 - 构造函数修正:修复了原代码中调用父类构造函数时的参数错误,解决
$products误传的问题。 - 严格验证逻辑:
- 遍历传入数组,检查每个键是否为字符串类型,确保是产品名称
- 检查每个值是否为
Product类的实例 - 可选验证:确保数组键与产品实例的
name属性一致,避免数据不一致
- 类型声明:对构造函数参数和方法参数添加
array类型声明,明确参数类型。
内容的提问来源于stack exchange,提问作者Raitiko
相关产品推荐
相关产品推荐

