У меня есть сценарий, в котором у меня есть несколько классов, которые происходят от общего предка, потому что все они имеют общие свойства и методы. Половина этих классов (группа A) содержит свойство, которое не используется другой половиной (группа B), поэтому каждый класс в группе A явно объявляет это свойство, а не родительский класс.
например.
class parent
{
}
class child1 <and child2, and child3> extends parent
{
protected $specialProperty;
}
class child4 <and child5, and child5> extends parent
{
// no "$specialProperty"
}
У меня есть некоторое поведение, которое мне нужно реализовать, которое действует на $specialProperty
. Естественно, я хотел бы поместить это в родительский класс и сделать это только один раз, но $specialProperty
существует не во всех дочерних классах.
Один из вариантов - создать промежуточный абстрактный класс, который объявляет $specialProperty
и реализует требуемое поведение, но я не хочу этого делать по нескольким причинам:
- Этот сценарий будет развиваться более скоро. Что мне тогда делать? Создать 5 или 6 различных промежуточных абстрактных классов для каждой из этих функций?
- Иерархия классов уже на 5 уровней выше
parent
. Должен ли я действительно создавать все больше и больше слоев, чтобы компенсировать неидеальную иерархию классов, которая была спешно разработана с ограниченными требованиями?
- По крайней мере, что касается PHP, не приведет ли так много уровней наследования к проблемам с производительностью?
Другой вариант заключается в следующем:
class parent
{
public function functionThatTheAppWillCallAutomatically()
{
if ( property_exists($this, 'specialProperty') )
{
// do stuff with specialProperty
}
}
}
"вещи" будут выполняться дочерними классами, которые имеют $specialProperty
и пропускаются теми, кто этого не делает. Я ненавижу это решение, хотя, потому что оно мне просто кажется неправильным и небрежным. По моему мнению, родитель не должен решать, что делать, основываясь на свойствах ребенка (черт возьми, он, вероятно, даже не должен знать, что ребенок существует - разве это не причина для дочернего класса в первую очередь ?)
Короче говоря, я не уверен, какой из этих двух вариантов наименее плох, или есть ли лучшая возможность. Я с нетерпением жду предложений.
Спасибо!
EDIT:
Я сделал следующее, чтобы реализовать эту специализированную функциональность.
class archivalDecorator extends decoratorBase /* decoratorBase just has constructor and the object property */
{
public function archive()
{
if ( !$this->object->archive() )
{
return false;
}
if ( property_exists($this->object, 'specialProperty') )
{
// do extra stuff here that involves "specialProperty"
}
return true;
}
}
Таким образом, все мои объекты выполняют один и тот же рабочий процесс архивирования, но классы, которые требуют особого поведения, могут выполнять его, и мне не нужно реализовывать десятки подклассов в иерархии для этих особых случаев.
Хотя я все еще использую property_exists(...)
, чтобы определить, нужно ли специальное поведение или нет, я думаю, что сейчас все в порядке, потому что я не делаю это из родительского класса. $specialProperty
является публичным свойством, поэтому нет никаких причин, по которым внешние классы не должны знать об этом, но что-то не так в родительском классе, проверяющем это свойство в дочернем классе с помощью $this
.
Надеюсь, я не неправильно применил эту концепцию.