我读过类结构的例子通常以基类开始,并且基类通过更精细的类扩展,即。经常被引用:
class Animal {}
class Rodent extends Animal {}
class Mouse extends Rodent {}
但是在我的CMS /电子商务系统的现实世界项目中,我似乎正在以相反的方式构建这种结构,即从一种类型的基础开始,并用与整个项目相关的东西扩展它但实际上并不是延伸班。
class page {}
class product extends page{}
class category extends product{}
class basket extends category{}
class shop extends basket{}
所以这样我只是调用$ s = new shop()并访问运行商店所需的所有类/方法。我想我只是扩展类来保存单独实例化每个类。对于我读过的大多数例子来说,这似乎是倒退的,我肯定错过了OOP的全部内容。我的课程似乎越来越普遍,而且随着课程的扩展而变得不那么专业。
我应该继续这种方式还是重构我如何构建这个类系统?
答案 0 :(得分:3)
您所做的只是将继承作为重用代码的一种方式,而这实际上并不是它的意思。继承旨在模拟描述为is a
的关系(也允许重复使用代码)。
product
不是page
,而page
可能列出 product
。
答案 1 :(得分:3)
您可以谷歌合成而不是继承和是-a vs has -a 。
在你的设计草图中,你注意到混合了一堆东西。解剖最简单的例子是class category{} extends product
。一类不是产品,但它包含/包含多种产品。这样更合适:
class product {
public $title; // for simplicity
public $price; // for simplicity
}
class category {
private $name;
private $products;
public function __construct($name) {
$this->name = $name;
$this->products = array();
}
public function addProduct(product $p) {
$this->products[] = $p;
}
public function printProducts() {
$product_names = array_map(function($product) {
return $product->title;
}, $this->products);
echo implode(', ', $product_names);
}
}
$c = new category('fruits');
$apple = new product;
$apple->title = 'apple';
$orange = new product;
$orange->title = 'orange';
$banana = new product;
$banana->title = 'banana';
$c->addProduct($apple);
$c->addProduct($orange);
$c->addProduct($banana);
$c->printProducts();
请注意如何将两个实体分开,让product
担心产品是什么和可以做什么,以及类别是什么(名称),有(产品)和可以做什么(打印其产品列表)。
解耦的另一个技巧(最小化类之间的依赖关系)是你应该尽可能长时间地保持数据不被你的对象。上面示例中的类是简单但功能性的。如果你可以让它们在没有数据库访问的情况下工作(这是拥有大量extends
链的常见原因),你会发现这些类都不需要数据库访问,而是可以通过类来填充/创建它们。有权访问数据库。像这样:
class category_factory {
public function __construct(PDO $pdo) { $this->pdo = $pdo; }
public function getCategories() {
$rows = $this->pdo->query("SELECT * FROM categories")->fetchAll();
$categories = array();
foreach($rows as $row) {
$categories[] = new category($row['name']);
}
return $categories;
}
}
* PDO包含数据库连接
答案 2 :(得分:2)
您应该将'extends'读作'是a(n)'。鼠标是啮齿动物,啮齿动物是动物。你的其他课程的情况并非如此。
如果你想要实现的关系可以被描述为'有一个(n)',你应该使用成员变量。
答案 3 :(得分:1)
是的,你似乎确实倒退了。
类别可能是一组产品,类似于一篮子。但是,由于篮子可能提供与产品相同的界面(例如成本,重量),因此更有可能将其作为产品集合实现,而不是扩展产品类别。 OTOH跟踪一个类别的总成本没有多大意义。因此,虽然类别和购物篮都是产品的集合,但它们并非紧密相关。
“页面”实体在产品方面没有多大意义 - 产品可能会有一个与之关联的页面实例。
在PHP中,类不是很重要 - 重要的是接口(即暴露了哪些方法),因此您不需要坚持刚性的对象层次结构。
答案 4 :(得分:0)
类之间应始终存在逻辑关系。只需将products
,categories
,shop
视为不在继承链中的单个对象。这些对象将使用方法调用进行通信,这是真正的oops范例。您还可以识别在所有这些对象中常见的一些属性和方法。所以这些类都可以扩展单个父类,比如page
。