2011-09-20 98 views
3

示例我讀到的類結構通常以基類開始,並且該基類會擴展更精細的類,即。經常被引用:組織類 - 幫助OOP初學者

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

但在CMS /電子商務系統的我的現實世界的項目,我似乎是建立這種結構的其他方式,即開始對一種類型的situtation的一類,並與一些相關的擴展它到整個項目,而不是實際到擴展課程。

class page {} 
class product extends page{} 
class category extends product{} 
class basket extends category{} 
class shop extends basket{} 

所以這種方式我只是調用$ s = new shop()並獲得所需的所有類/方法來運行商店。我想我只是擴展類來保存實例化每個單獨。這看起來倒退了我讀過的大多數例子,我肯定會忽略OOP的全部內容。隨着課程的擴展,我的課程似乎越來越普遍,專業化程度也越來越低。

我應該以這種方式繼續還是重構我如何構建這個課堂系統?

+1

谷歌**在繼承組成**和**是-A對具有-A **。 – chelmertz

+0

@chelmertz請將您的評論擴大到答案。 –

+0

@OZ_肯定的東西 – chelmertz

回答

3

你可以谷歌組成繼承is-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

您應該將'extends'看作'是(n)'。老鼠是齧齒動物,齧齒動物是動物。其他課程並非如此。

如果你想要實現的關係可以被描述爲'有(n)',你應該使用成員變量。

3

你在做什麼只是使用繼承作爲重用代碼的方式,這並不是真正意義上的。繼承意味着模擬描述爲is a(也允許重新使用代碼)的關係。

一個product不是page,但page威力列表product秒。

看看http://en.wikipedia.org/wiki/Object-oriented_design獲得靈感!

+0

使用繼承是重用代碼的一種方法。 –

+0

授予@OZ_,但不符合海報的做法。更新答案。 –

1

是的,你似乎有東西倒退。

一個類別大概是一組產品,同樣一個籃子。但是由於籃子可能提供與產品相同的界面(例如成本,重量),因此更有可能將此作爲產品集合來實施,而不是擴展產品類別。 OTOH跟蹤類別的總成本沒有多大意義。所以儘管類別和籃子都是產品的集合,但它們之間並沒有緊密的聯繫。

'頁面'實體與產品沒有很大關係 - 當然,產品可能有一個與其關聯的頁面實例。

在PHP中,類不是很重要 - 重要的是接口(即暴露的方法),所以你不需要堅持剛性的對象層次結構。

0

類之間應該總是存在邏輯關係。只需將products,categories,shop作爲不在繼承鏈中的單個對象。這些對象將使用方法調用進行通信,這是真正的oops範例。你也可以確定一些在所有這些對象中都很常見的屬性和方法。所以所有這些類都可以擴展單個父類,如page