организация занятий - помощь новичку в ООП - PullRequest
3 голосов
/ 20 сентября 2011

Примеры, которые я читаю о структуре класса, обычно начинаются с базового класса, и этот базовый класс расширяется за счет более совершенных классов, т.е.часто цитируемые:

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 () и получаю доступ ко всем классам / методам, необходимым для запускамагазин.Я предполагаю, что я просто расширяю классы, чтобы сохранить создание каждого из них отдельно.Это кажется задом наперед к большинству примеров, которые я прочитал, и мне, конечно, не хватает того, что ООП здесь все.Кажется, что мои классы становятся более общими и менее специализированными по мере расширения.

Должен ли я продолжать таким образом или реструктурировать то, как я строю эту систему классов?

Ответы [ 5 ]

3 голосов
/ 20 сентября 2011

Вы можете гуглить композицию через наследование и is-a против 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 содержит соединение дБ

3 голосов
/ 20 сентября 2011

То, что вы делаете, использует наследование только как способ повторного использования кода, что на самом деле не то, для чего он предназначен.Наследование предназначено для моделирования отношений, которые описываются как is a (которые также допускают повторное использование кода).

A product не является page, но page может list product s.

Взгляните на http://en.wikipedia.org/wiki/Object-oriented_design для вдохновения!

2 голосов
/ 20 сентября 2011

Вы должны прочитать «extends» как «is (n)». Мышь - это Грызун, Грызун - это Животное. Это не относится к другим вашим классам.

Если отношение, которое вы пытаетесь реализовать, можно описать как 'has a (n)', вам следует использовать переменные-члены.

1 голос
/ 20 сентября 2011

Да, у вас, похоже, все наоборот.

Категория, по-видимому, представляет собой группу товаров, аналогично корзине. Но поскольку корзина может обеспечивать некоторый интерфейс, аналогичный продукту (например, стоимость, вес), более вероятно, что она будет реализована как набор продуктов, а не как расширение класса продукта. OTOH нет смысла отслеживать общую стоимость категории. Таким образом, хотя и категория, и корзина являются коллекциями товаров, в остальном они тесно не связаны.

Сущность 'page' не имеет большого смысла в отношении продукта - конечно, продукт может иметь экземпляр страницы, связанной с ним.

В PHP класс не очень важен - важен интерфейс (т. Е. Какие методы доступны), поэтому вам не нужно придерживаться жесткой иерархии объектов.

0 голосов
/ 20 сентября 2011

Между классами всегда должна быть логическая связь. Просто представьте себе products, categories, shop как отдельные объекты, которые не входят в цепочку наследования. Эти объекты будут взаимодействовать с использованием вызовов методов, что является настоящей парадигмой упс. Также вы можете определить некоторые свойства и методы, которые будут общими для всех этих объектов. Таким образом, все эти классы могут расширять один родительский класс, скажем page.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...