组织课程 - 帮助OOP初学者

时间:2011-09-20 07:58:30

标签: php oop inheritance

我读过类结构的例子通常以基类开始,并且基类通过更精细的类扩展,即。经常被引用:

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的全部内容。我的课程似乎越来越普遍,而且随着课程的扩展而变得不那么专业。

我应该继续这种方式还是重构我如何构建这个类系统?

5 个答案:

答案 0 :(得分:3)

您所做的只是将继承作为重用代码的一种方式,而这实际上并不是它的意思。继承旨在模拟描述为is a的关系(也允许重复使用代码)。

product不是page,而page可能列出 product

看看http://en.wikipedia.org/wiki/Object-oriented_design获取灵感!

答案 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)

类之间应始终存在逻辑关系。只需将productscategoriesshop视为不在继承链中的单个对象。这些对象将使用方法调用进行通信,这是真正的oops范例。您还可以识别在所有这些对象中常见的一些属性和方法。所以这些类都可以扩展单个父类,比如page