Разница между признаком и абстрактным классом в PHP

Недавно я встретил Traits в PHP и попытался их понять. Во время моего исследования я наткнулся на этот вопрос SO: Черты против интерфейсов. В принятом ответе упоминается следующее:

Интерфейс определяет набор методов, которым должен обладать класс реализации реализовать.

Когда используется признак, реализуются реализации методов тоже - что не происходит в интерфейсе.

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

  • В чем разница между чертой и абстрактным классом в PHP?

Я знаю, что я могу распространяться только из одного абстрактного класса, а с другой стороны использовать любое количество признаков. Но разве это единственное различие? Я все еще не совсем понимаю черты и их использование, поэтому надеюсь, что это не глупый вопрос.

Ответ 1

Черты позволяют вам делиться кодом между вашими классами , не заставляя вас в определенной иерархии классов. Скажем, вы хотите, чтобы все ваши классы имели удобный метод утилиты foo($bar); без признаков у вас есть два варианта:

  • реализовать его индивидуально с избыточным кодом в каждом классе
  • наследуется от общего (абстрактного) класса предков

Оба решения не идеальны, каждый с их различными компромиссами. Очевидно, что избыточность кода нежелательна, и наследование от общего предка делает вашу иерархию классов негибкой.

Черты решают эту проблему, позволяя вам реализовать foo($bar) в признаке, который каждый класс может "импортировать" индивидуально, но при этом позволяя вам создавать иерархию классов в соответствии с требованиями бизнес-логики, а не требованиями к языку.

Ответ 2

Не совсем... Позвольте процитировать официальную документацию для этой цели:

A Trait похож на класс, но предназначен только для группы функциональность в тонкой и последовательной форме. Это невозможно чтобы создать экземпляр "Трейта" самостоятельно. Это дополнение к традиционным наследование и обеспечивает горизонтальный состав поведения; то есть, применение членов класса без необходимости наследования.

Итак, черты используются для целей композиции, чтобы позволить классу выполнять некоторую логику/поведение. Если вы наследуете от другого/абстрактного класса, это обычно для целей полиморфизма, и вы получаете отдельную иерархию наследования/класса, которая может быть или не быть желательной.

Я думаю, все зависит от контекста, архитектуры и того, что именно вы пытаетесь сделать.