Недавно я начал изучать ООП, и теперь я нахожусь в такой ситуации, что чем больше я читаю о различиях между абстрактными классами и интерфейсами, тем больше я запутываюсь. Пока что ни один из них не может быть создан. Интерфейсы - это более или менее структурные чертежи, определяющие структуру и тезисы, которые отличаются частичной реализацией кода.
Я хотел бы узнать больше об этом через мою конкретную ситуацию. Вот ссылка на мой первый вопрос, если вы хотите немного больше справочной информации: Какая модель дизайна подходит для моего нового класса?
Вот два класса, которые я создал:
class Ad {
$title;
$description
$price;
function get_data($website){ }
function validate_price(){ }
}
class calendar_event {
$title;
$description
$start_date;
function get_data($website){ //guts }
function validate_dates(){ //guts }
}
Итак, как видите, эти классы практически идентичны. Здесь не показано, но есть и другие функции like get_zip()
, save_to_database()
общие для всех моих классов. Я также добавил другие классы автомобилей и домашних животных, которые имеют все общие методы и, конечно, свойства, характерные для этих классов (например, пробег, вес).
Теперь я нарушил принцип СУХОГО, и я управляю и изменяю один и тот же код в нескольких файлах. Я намереваюсь иметь больше классов, таких как лодки, лошади или что-то еще.
Так это где я бы использовал интерфейс или абстрактный класс? Из того, что я понимаю об абстрактных классах, я бы использовал суперкласс в качестве шаблона со всеми общими элементами, встроенными в абстрактный класс, а затем добавил бы только те элементы, которые конкретно необходимы в будущих классах. Например:
abstract class content {
$title;
$description
function get_data($website){ }
function common_function2() { }
function common_function3() { }
}
class calendar_event extends content {
$start_date;
function validate_dates(){ }
}
Или я бы использовал интерфейс и, поскольку они очень похожи, создал бы структуру, которую каждый из подклассов вынужден использовать по соображениям целостности, и оставил это на усмотрение конечного разработчика, который конкретизирует этот класс, чтобы отвечать за каждый из детали даже общих функций. я думаю, что некоторые «общие» функции, возможно, придется изменить в будущем для нужд своего конкретного класса.
Несмотря на все вышесказанное, если вы считаете, что я неправильно понимаю, что и почему абстрактных классов и интерфейсов в целом, непременно дайте правильному ответу перестать думать в этом направлении и предложите правильный путь для продвижения вперед!
Благодарность!
Ответы:
С точки зрения непрофессионала:
Интерфейсы предназначены для типа «можно сделать / можно рассматривать как» .
Абстрактные (а также конкретные) классы предназначены для «это» своего рода отношений.
Посмотрите на эти примеры:
Bird
,Mosquito
ИHorse
являютсяAnimals
. Они связаны. Они наследуют общие методы от животных, какeat(), metabolize() and reproduce()
. Возможно, они переопределяют эти методы, добавляя к ним немного больше, но они используют преимущества поведения по умолчанию, реализованного в Animal, напримерmetabolizeGlucose().
Plane
не имеет отношения кBird
,Mosquito
илиHorse
.Flight
реализуется различными, не связанными классами, какBird
иPlane
.AccountableAsset
также реализуется различными, не связанными классами, такими какPlane
иRaceHorse
.Horse
не осуществляет полет.Как вы видите, классы (абстрактные или конкретные) помогают строить иерархии , позволяя вам наследовать код от верхних уровней до нижних уровней иерархии. Теоретически, чем ниже вы находитесь в иерархии, тем более специализировано ваше поведение, но вам не нужно беспокоиться о многих вещах, о которых уже позаботились.
Интерфейсы , с другой стороны, не создают иерархию, но они могут помочь гомогенизировать определенные поведения в иерархиях, чтобы вы могли абстрагировать их от иерархии в определенных контекстах.
Например, вы можете иметь программную сумму значения группы
AccountableAssets
независимо от того, кем они являютсяRaceHorses
илиPlanes
.источник
can do/can be treated as
где абстрактные классы действуют как фундаментальные!Вы могли бы вывести ответ логически, так как вы, кажется, знаете о различиях между ними.
Интерфейсы определяют общий контракт. Такой как интерфейс под названием IAnimal, где все животные имеют общие функции, такие как Eat (), Move (), Attack () и т. Д. Хотя все они имеют одни и те же функции, все или большинство из них имеют разные способы (реализации) достижения Это.
Абстрактные классы определяют общую реализацию и, возможно, общие контракты. Например, простой калькулятор может квалифицироваться как абстрактный класс, который реализует все основные логические и побитовые операторы, а затем расширяется с помощью ScientificCalculator, GraphicalCalculator и так далее.
Если у вас есть общая реализация, во что бы то ни стало, инкапсулируйте функциональность в абстрактный класс для расширения. У меня около 0 опыта PHP, но я не думаю, что вы можете создавать интерфейсы с непостоянными полями. Если поля являются общими для ваших классов экземпляров, вы вынуждены использовать абстрактный класс, если только вы не определяете доступ к ним через методы получения и установки.
Кроме того, в Google нет недостатка в результатах.
источник
Короче. Абстрактные классы очень похожи на интерфейсы в том, что они оба предоставляют шаблон того, какие методы должны быть в наследующем классе, но есть большие различия: - интерфейсы определяют только имена / типы методов, которые должны существовать в наследующем классе, тогда как классы могут иметь полный код метода по умолчанию, и может потребоваться переопределить только детали. - Интерфейсы не могут иметь модификаторы доступа. - Интерфейсы не могут иметь полей. - Классы не могут иметь множественное наследование классов, в то время как они могут наследовать несколько интерфейсов. - Кроме того, классы предоставляют иерархическую структуру, так что только классы, производные от определенного класса, должны следовать рекомендациям абстрактного класса: объект-> конкретный объект-> очень специфический объект. Интерфейсы с другой стороны могут быть унаследованы кем угодно и где угодно.
На мой взгляд, абстрактные классы более распространены в том смысле, что они могут обеспечить реализацию кода по умолчанию сразу, но в крупных проектах, где необходимо стандартизировать определенные классы, интерфейсы могут пригодиться.
Надеюсь, это поможет, но есть много информации об этом онлайн, Лео
источник
Classes cannot have multiple inheritance
- Верно для языков, таких как Java и C #, не верно для C ++.Прежде всего, вы должны понимать, что вы часто будете предоставлять как интерфейс, так и абстрактный класс. Причина этого и основное различие между ними заключается в том, что они позволяют повторно использовать другой код и таким образом решать различные проблемы.
Интерфейсы позволяют повторно использовать клиентский код с различными реализациями. Клиент вашего класса get_data ($ website) не заботится об элементах $ title или $ description. Он просто хочет, чтобы ваш контент загружал данные. Если у вас есть разные типы контента, некоторые из которых требуют описания $, а некоторые нет, вы можете предоставить класс ContentInterface, который определяет только сигнатуру ваших дочерних классов. Теперь клиент может иметь любое количество различных контентов, не зная точно, как они работают. Принцип подстановки Лискова - хорошая вещь для изучения этой идеи. Мне также нравится, что дядя Боб пишет на эту тему. Интерфейсы очень важны для модульного тестирования, и создание интерфейсов - хорошая привычка для изучения.
Абстрактные классы позволяют вам повторно использовать общие детали реализации в наборе классов, которые имеют общего предка. В вашем вопросе вы, кажется, хорошо понимаете, почему вы наследуете реализацию от абстрактного класса. Все еще опасно зависеть от внутренних элементов базового класса - очень легко нарушить инкапсуляцию и создать дочерние элементы, которые зависят от конкретных деталей реализации базового класса. Метод Шаблон Шаблон представляет собой общий и здоровый пример того , как использовать базовые классы , не нарушая инкапсуляцию.
Итак, как я надеюсь, я показал, что вы часто будете предоставлять интерфейсы для клиентов вашей иерархии классов, чтобы вы могли безопасно изменять свою реализацию, не влияя на клиентский код. Это позволяет клиенту писать модульные тесты, используя Mock Objects, которые наследуют ваш интерфейс. Также вы предоставите абстрактные классы, которые позволяют повторно использовать общую логику или применять семантику для дочерних классов.
источник
Разница тонкая, но ясная. Интерфейс о полиморфном поведении. Абстрактный класс о повторном использовании и полиморфном поведении.
Если вы хотите сделать упор на повторное использование и полиморфное поведение, выберите абстрактный класс. Например, сотрудники разных типов имеют разные положения, но все получают несколько общих. Таким образом, абстрактный класс подходит для его представления, поскольку общие черты могут быть выражены в базовом абстрактном классе,
Employee
а различие может быть реализовано в производных классах, таких какManager
илиWorker
т. Д.Если вы хотите сделать акцент только на полиморфном поведении, выберите интерфейс. Интерфейс - это скорее контракт, т. Е. Объект или иерархия, говорящие, что он соответствует определенному поведению. Например, все сотрудники имеют предоставление отпуска, но разные типы сотрудников имеют различные типы обеспечения. Таким образом, для каждого сотрудника другого типа требуется свой калькулятор отпуска. Здесь интерфейс является хорошим выбором, потому что все типы сотрудников могут реализовывать
LeaveCalculator
интерфейс сCalculate()
поведением по-разному.источник
источник