开发者

organizing classes - help for an OOP beginner

Examples I read of class structure typically begin with a base class and that base class gets extended with more refined classes ie. the often quoted:

class Animal {}
class Rodent extends Animal {}
class Mouse extends Rodent {}

But in my real world project of a CMS/ecommerce system I seem to be building this structure the other way around i.e. starting with a class for one type of situtation and extending it with something related to the whole project but not actually to the extending class.

class page {}
class product extends page{}
class category extends product{}
class basket extends category{}
c开发者_高级运维lass shop extends basket{}

So this way I am just calling $s = new shop() and getting access to all the classes/methods needed to run the shop. I suppose I am just extending the classes to save instantiating each one separately. This seems backwards to most examples I have read and I'm surely missing what OOP is all about here. My classes seem to be getting more general and less specialised as they get extended.

Should I continue in this way or restructure how I am building this class system?


You could google composition over inheritance and is-a vs has-a.

In your design sketch, you mix up a bunch of stuff as you noticed. The easiest example to dissect would be class category{} extends product. One category is not a product, but it has/contains several products. This would be more suitable:

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();

Notice how you keep both entities separated and let product worry about what a product is and can do, and what a category is (name), has (products) and can do (print a listing of its products).

Another tip for decoupling (minimizing dependencies between classes) is that you should try to keep data out of your objects for as long as possible. The classes in the example above are simplistic but functional. If you can make them work without database access (which is a common reason to have a huge chain of extends), you realize that none of these classes needs database access and that they instead can be filled/created by classes that do have access to the database. Something like this:

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 contains a db connection


What you're doing is using inheritance only as a way to reuse code, which is not really what it is meant for. Inheritance is meant to model a relationship that is described as is a (which also allow re-use of code).

A product is not a page, but a page might list products.

Take a look at http://en.wikipedia.org/wiki/Object-oriented_design for inspiration!


You should read 'extends' as 'is a(n)'. A Mouse is a Rodent, a Rodent is an Animal. That's not the case with your other classes.

If the relation you're trying to realize can be described as 'has a(n)', you should use member variables.


Yes, you do seem to have got things backwards.

A category presumably is a group of products, similarly a basket. But since a basket might provide some of the same interface as a product (e.g. cost, weight) It'd be more likely to implement this as a collection of products rather than extending the product class. OTOH it doesn't make much sense to track the total cost of a category. So although both category and basket are collections of products, they are not otherwise closely related.

The 'page' entity doesn't make a lot of sense in relation to the product - certainly a product might have an instance of a page associated with it.

In PHP the class is not very important - what is important is the interface (i.e. what methods are exposed) so you don't need to stick to a rigid object hierarchy.


There should always be a logical relation between classes. Just think of products, categories, shop, as individual objects which is not in inheritance chain. These objects will be communicating using method calls, which is the real oops paradigm. Also you can identify some properties and methods that will be common in all these objects. So all these classes can extend a single parent class, say page.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜