Я знаю, что не могу расширяться из двух классов, но какова альтернатива для моего случая?
Я использую базовый класс, parser
, то есть парсер страницы моей CMS. Этот класс содержит все основные функции, необходимые для фильтрации данных, извлеченных из базы данных, и преобразования их в HTML-страницу.
Всем остальным классам нужен парсер, потому что без него они не работают.
У меня 2 режима:
Внутри CMS
Если внутри CMS, userdata и другие дополнительные данные загружаются в класс.
Вне CMS
Если за пределами CMS загружаются только необходимые данные для отображения страницы, это способ отображения страниц по умолчанию для людей, посещающих сайт.
Модули
Страница может использоваться для отображения данных / элементов по умолчанию, но она также может использоваться для отображения данных из модуля (например, страницы календаря).
Если это так, то в объект синтаксического анализа необходимо загрузить дополнительные данные, и поэтому у меня есть 4 различных варианта использования:
У меня есть следующие [чрезвычайно упрощенные] классы:
class parser {
protected $oDataSource1;
protected $oDataSource2;
protected $oDataSource3;
//...
public function filterData() {
//.. Search through the data sources and return filtered data
}
}
class cmsParser extends parser {
protected $sUser_name;
protected $iUser_id;
protected $sUserLanguage;
///.. some functions here that are called only within the CMS
}
class moduleParser extends parser {
protected $mModuleData;
//.. Do something with this moduleData;
}
class cmsModuleParser extends ?? {
//... Get functions from the cmsParser + module functions
}
Единственное решение, которое я могу придумать, это использовать черту, которую используют moduleParser и cmsModuleParser?
Это не оптимальное IMO, потому что я все еще должен добавить дубликаты переменных и т. Д.
Конечно, я не хочу дублировать код, так как мне решить эту загадку?
Вы слышали фразу отдать предпочтение композиции перед наследованием? Иногда композиция будет платить больше, чем наследование. В этом случае cmsModuleParser extends cmsParser
а затем вводит moduleParser
через конструктор как зависимость. Тем не менее, у вас также есть getter
и setter
для $moduleParser
Имущество. Так что если вам не нужно вводить его через конструктор, вы все равно можете удалить его из конструктора и использовать setModuleParser()
Метод доступа вместо. Кроме того, вы также можете запрограммировать интерфейс. Ниже приведен код, который иллюстрирует обе концепции:
СОСТАВ
<?php
class parser {
protected $mData;
//...
public function filterData() {
//.. filter the data here and return it
}
}
class cmsParser extends parser {
protected $sUser_name;
protected $iUser_id;
protected $sUserLanguage;
///.. some functions here that are called only within the CMS
}
class moduleParser extends parser {
protected $mModuleData;
//.. Do something with this moduleData;
}
// HERE YOU EXTEND THE cmsParser
// AND THEN USING DI, INCLUDE THE moduleParser
class cmsModuleParser extends cmsParser {
/**
* @var ModuleParser
*/
protected $moduleParser;
//... Get functions from the cmsParser + module functions
public function __construct(moduleParser $moduleParser) {
}
/**
* @return moduleParser
*/
public function getModuleParser() {
return $this->moduleParser;
}
/**
* @param moduleParser $moduleParser
* @return cmsModuleParser
*/
public function setModuleParser($moduleParser) {
$this->moduleParser = $moduleParser;
return $this;
}
}
ПРОГРАММИРОВАНИЕ В ИНТЕРФЕЙС
<?php
interface iParser{
public function filterData();
public function renderView();
public function saveData();
}
class parser implements iParser{
protected $mData;
//...
public function filterData() {
//.. filter the data here and return it
}
public function renderView(){}
public function saveData(){}
}
class cmsParser extends parser {
protected $sUser_name;
protected $iUser_id;
protected $sUserLanguage;
///.. some functions here that are called only within the CMS
}
class moduleParser extends parser {
protected $mModuleData;
//.. Do something with this moduleData;
}class cmsModuleParser implements iParser {
//... Get functions from the cmsParser + module functions
public function __construct() {
}
public function filterData(){}
public function renderView(){}
public function saveData(){}
}
Прежде всего вы должны знать тот факт, что все классы расширяют один класс, который считается плохим проектом и указывает, что вы плохо понимаете концепции ОО.
Наследование что-то вроде A is a B
, То есть все ваши классы — это cmsParser. Это, конечно, неправильно и вызовет такие проблемы, к которым вы обращаетесь. Есть много примеров, когда наследование полезно как
Но наследство вроде
не очень хороший дизайн, и проблема очевидна.
Итак, как вы решаете свою проблему?
Давайте придерживаться Car
дело. Сначала определите класс автомобиля
class Car extends Engine{
public function reverse(){
$this->startEngine();//Parent's method.
.....
}
вместо вышеперечисленного вы можете сделать что-то вроде этого
class Car{
protected $Engine;
protected $Driver;
public function __construct($Engine, $Driver){
$this->Engine = $Engine;
$this->Driver = $Driver;
}
public function reverse(){
$this->Engine->start();
$this->Driver->LookBehindYou();
...
}
}
Таким образом, используя инъекцию contstructor, вы получаете слабую связь между вашими зависимостями и получаете лучший дизайн.
Поиск в Google о Инъекция зависимости а также Композиция по наследству consepts.