Не один раз написано о том, в чем разница между интерфейсом и абстрактным классом. В большинстве случаев разговор заканчивается фразами, сводящимися к следующему: "Абстрактный класс — это абстрактный класс, а интерфейс — это интерфейс..."
Могли бы вы ответить на простой вопрос: В каких случаях при проектировании вы делаете выбор в пользу интерфейса, а в каких — в пользу абстрактного класса? Какими признаками должны обладать сущности предметной области, чтобы быть отнесенными к интерфейсам? А к абстрактным классам?
Я думаю так или иначе все сталкиваются с предметной областью . И наверняка многие имеют опыт ее анализа. Очень хотелось бы зачерпнуть немного ваших знаний .
P.S. Разумеется, вопрос относиться к конкретному языку — Java, но и к понятию "интерфейс" как таковому.
03.07.06 13:19: Перенесено модератором из 'Java' — Blazkowicz
Re: Проектирование: интерфейс vs абстрактный класс
Я вообще не вижу смысла в а,страктных классах кроме как инкапсуляция общей (generic) или default логики всех (или большинства) имплементаций интерфейса.
Пример из Swing'а:
interface TableModel
abstact class AbstactTableModel implments TableModel — абстрактный класс с default логикой которая подходит большинству имплементаций TableModel
class OrdersTableModel extends AbstactTableModel — пользуется default логикой определенной в AbstactTableModel, там где надо переопределяет методы.
Мне кажется что вся эта дискуссия пошла из С++ где не было интерфейсов и вместо них использовались абстрактные классы (но там есть множественное наследование ), соответсвенно при переходе на Java часто возникает вопрос а зачем еще интерфейсы.
Re[2]: Проектирование: интерфейс vs абстрактный класс
Здравствуйте, boluba, Вы писали:
B>Не один раз написано о том, в чем разница между интерфейсом и абстрактным классом. В большинстве случаев разговор заканчивается фразами, сводящимися к следующему: "Абстрактный класс — это абстрактный класс, а интерфейс — это интерфейс..."
Интерфейсы были введены в Java, сколько бы не говорили о "принципах ОО", чтобы решить проблему множественного наследования. В Java нельзя множественно наследовать классы, но можно это обойти с помощью интерфейсов. В результате — никаких "ромбиков" и прочих "перегрузок" нет.
B>Могли бы вы ответить на простой вопрос: В каких случаях при проектировании вы делаете выбор в пользу интерфейса, а в каких — в пользу абстрактного класса? Какими признаками должны обладать сущности предметной области, чтобы быть отнесенными к интерфейсам? А к абстрактным классам?
Любой интерфейс — это то что лежит сверху. С кнопками. Чего там внутри — не важно. Есть кнопки и надписи на них. чтобы определить их — нужен интерфейс.
Абстрактный класс — это базовая прослойка, между интерфейсом и всем разнообразием, его реализующим. Ну например ControlPanel — интерфейс, AbstractControlPanel implements ControlPanel — базовая реализация, DefaultControlPanel extends AbstractControlPanel — какая то реализация.
На мой взгляд, хорошим примером продуманной архитекруты можно считать Swing. Там есть (не всегда конечно) то о чем я говорил. Например ListModel, AbstractListModel и DefaultListModel. Ну и так далее.
А вот Collections Framework на мой взгляд спроектирован ужастно. Взять хотябы List, AbstractList и ArrayList. Вроде все тоже самое, но внутри все сделано по-дурацки.
Re: Проектирование: интерфейс vs абстрактный класс
Здравствуйте, boluba, Вы писали:
B>Не один раз написано о том, в чем разница между интерфейсом и абстрактным классом. В большинстве случаев разговор заканчивается фразами, сводящимися к следующему: "Абстрактный класс — это абстрактный класс, а интерфейс — это интерфейс..."
Поиск так же показывает много других интересных постов по теме.
B>Могли бы вы ответить на простой вопрос: В каких случаях при проектировании вы делаете выбор в пользу интерфейса, а в каких — в пользу абстрактного класса? Какими признаками должны обладать сущности предметной области, чтобы быть отнесенными к интерфейсам? А к абстрактным классам?
Честно говоря никогда не приходилось сталкиватся с такой проблемой выбора. Вроде всегда ясно где что приемнять.
B>Я думаю так или иначе все сталкиваются с предметной областью . И наверняка многие имеют опыт ее анализа. Очень хотелось бы зачерпнуть немного ваших знаний .
А мне хотелось бы посмотреть на пример (не оторваный от жизни) в котором на первый взгляд одинаково хорошо подходят и абстрактный класс и интерфейс.
B>P.S. Разумеется, вопрос относиться к конкретному языку — Java, но и к понятию "интерфейс" как таковому.
Вообще-то у нас есть такие форумы как проектирование и философия.
Re[2]: Проектирование: интерфейс vs абстрактный класс
Здравствуйте, aefimov, Вы писали:
A>А вот Collections Framework на мой взгляд спроектирован ужастно. Взять хотябы List, AbstractList и ArrayList. Вроде все тоже самое, но внутри все сделано по-дурацки.
не понял наезда? это то же самое что "Взять хотяб американцев, тоже люди, но сделаны как-то по-дурацки". Объясни конкретно что именно в Collections "сделано по-дурацки"
Re[3]: Проектирование: интерфейс vs абстрактный класс
Здравствуйте, Lucker, Вы писали:
L>не понял наезда? это то же самое что "Взять хотяб американцев, тоже люди, но сделаны как-то по-дурацки". Объясни конкретно что именно в Collections "сделано по-дурацки"
Ну посмотри как сделан AbstractList. Мало того что абстрактные методы перегружают методы интерфейса, так еще там полно методов вот таких:
public Object set(int index, Object element) {
throw new UnsupportedOperationException();
}
Я конечно понимаю, это чтоб "делать mutable коллекции" и не парится. Только это не фига не правильно, базовая функциональность не должна запрещать вызов методов, объявленных в интерфейсе — это мягко говоря, бяка.
Re[3]: Проектирование: интерфейс vs абстрактный класс
Здравствуйте, malkolinge, Вы писали:
M>Интерфейс необходимо использовать тогда, когда классы различных иерархий должны иметь возможность единообразной работы.
Это понятно. Вопрос был не когда использовать интерфейсы. А как выбрать между интерфейсом и абстрактным классом
Re: Проектирование: интерфейс vs абстрактный класс
Здравствуйте, boluba, Вы писали:
B>Могли бы вы ответить на простой вопрос: В каких случаях при проектировании вы делаете выбор в пользу интерфейса, а в каких — в пользу абстрактного класса?
Выдержка из книги Горький вкус джава:
1. Если реализация может измениться, всегда используйте интерфейсы. При использовании абстрактных классов реализация может фиксироваться
2. Интерфейсы применяются для описания дополнительных возможностей (Printable, Serializable, Cloneable)
3. Интерфейсы используются в тех случаях, когда реализация по умолчанию не задана.
4. Абстрактные классы используются при частичном определении реализации по умолчанию
5. Иногда интерфейсы могут использоваться в сочетании с абстрактными классами для создания фиксированного интерфейса, комбинируемого с частичной реализацией. Такая комбинация продоставляет удобства частичной реализации с гибкостью интерфейсов.
суть в простоте, а простота в сути
Re: Проектирование: интерфейс vs абстрактный класс
Здравствуйте, boluba, Вы писали:
B>Не один раз написано о том, в чем разница между интерфейсом и абстрактным классом. В большинстве случаев разговор заканчивается фразами, сводящимися к следующему: "Абстрактный класс — это абстрактный класс, а интерфейс — это интерфейс..."
B>Могли бы вы ответить на простой вопрос: В каких случаях при проектировании вы делаете выбор в пользу интерфейса, а в каких — в пользу абстрактного класса? Какими признаками должны обладать сущности предметной области, чтобы быть отнесенными к интерфейсам? А к абстрактным классам?
B>Я думаю так или иначе все сталкиваются с предметной областью . И наверняка многие имеют опыт ее анализа. Очень хотелось бы зачерпнуть немного ваших знаний .
B>P.S. Разумеется, вопрос относиться к конкретному языку — Java, но и к понятию "интерфейс" как таковому.
Если очень кратко:
абстрактный класс может содержать реализацию.Иногда это удобно.
Если приложение правильно проектируется с точки зрения ООП, то очень часто самый первый класс в цепочке наследования — абстрактный.
Все стальное — в посте выше, там более подробно.
A> public Object set(int index, Object element) {
A> throw new UnsupportedOperationException();
A> }
A>
A>Я конечно понимаю, это чтоб "делать mutable коллекции" и не парится. Только это не фига не правильно, базовая функциональность не должна запрещать вызов методов, объявленных в интерфейсе — это мягко говоря, бяка.
Тут можно спорить. Использование UnsupportedOperationException прямо и подробно описано в документации по Collections Framework. Насколько я понимаю, вы считаете, что раз уж класс реализует интерфейс (контракт), то должен его реализовывать (исполнять) полностью. Но если еще раз подумать, то выброс UnsupportedOperationException является неотемлемой частью контракта в данном контексте, не находите? На ваш взгляд было бы лучше вместо десятка интерфейсов и базовых реализаций иметь сотни конкретных частных решений, не выбрасывающих UnsupportedOperationException?
Re[2]: Проектирование: интерфейс vs абстрактный класс
B>Поиск так же показывает много других интересных постов по теме.
Конечно не все. Но кнопку поиск использовал. Мой вопрос отличается от поднятых в вышеуказанных топиках, как и в большинстве других топиков на других форумах.
B>Честно говоря никогда не приходилось сталкиватся с такой проблемой выбора. Вроде всегда ясно где что приемнять.
Хм... Вот вы можете попытаться формализовать подход? Я говорю не об универсальной методике, способной раз и навсегда положить конец разговорам на эту тему, а о "сигналах", которые для вас значат: "вот это точно интерфейс".
B>А мне хотелось бы посмотреть на пример (не оторваный от жизни) в котором на первый взгляд одинаково хорошо подходят и абстрактный класс и интерфейс.
Возможно действительно стоило дать пример с самого начала. Пусть это будет "система поиска работы". job.ru, monster.com (не сочтите за джинсу ). Какие, на ваш взгляд, в этой задаче можно выделить классы и какие интерфейсы? И самое главное — почему? (Вопрос застрял где-то между дизайном и Java, если вы понимаете о чем я)
B>Вообще-то у нас есть такие форумы как проектирование и философия.
Вопрос ровно на столько относиться к языку, чтобы его не перемещать в "проектирование" и "философию" .
Re[5]: Проектирование: интерфейс vs абстрактный класс
Здравствуйте, boluba, Вы писали:
B>Тут можно спорить. Использование UnsupportedOperationException прямо и подробно описано в документации по Collections Framework.
Баги, которые описаны и задокументированы, перестают быть багами. (с) A.A.
... << RSDN@Home 1.1.4 stable rev. 510>>
Re: Проектирование: интерфейс vs абстрактный класс
Здравствуйте, elinson, Вы писали:
E>Odin iz wariantow (rabotaet daleko ne wsegda): E>Esli imja skoree prilagatelnoe (Serializable, Cloneable) — to Interface, Esli su6estwitelnoe — class.
E>MfG Stas
Спасибо, про этот метод я знаю. Но вот с его применением достаточно часто возникают проблемы (у меня). Используя этот подход, java.lang.Throwable должен был бы быть интерфейсом. А было ли бы это хорошим дизайном?
Re[6]: Проектирование: интерфейс vs абстрактный класс
То что в коллекциях порой выкидывается исключение, что метод не поддерживется?
или то что коллекции практически нельзя расширить или изменить(Josh Bloch)?
или то что в коллекциях нельзя хранить примитивы?
или то что существуют примитивы и объектные ссылки?
или ....?
Я считаю, что в java было сделано много оптимизаций. Может, раньше так и надо было, может без этого java не завоевала те позиции, на которых находится сейчас. Но, в итоге, я вижу достаточной сложный язык. Что бы начать программировать на java, на хорошем уровне, надо обязательно почитать JLS, а если хочешь работать с http — пару десятков книг: первая ссылка в рисунках, на Google: ruby vs java, я понимаю что во многом прикол, но доля правды в этом есть.
И если бы стандартная библиотека устраивала бы людей, не появлялись бы велосипеды:
commons-lang, commons-beanutils, javolution... – велосипеды дополняющий язык (java.lang) хорошими свойствами.
trove4j, commons-collections, commons-primitives, javolution... – велосипеды для коллекций (быстрые коллекции, коллекции для примитивных объектов и т.д.).
Так что у меня, к java не однозначное отношение, кое где хорошее, а кое где и не очень...
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[8]: Проектирование: интерфейс vs абстрактный класс
Здравствуйте, Petrovich_Alex, Вы писали:
P_A>Я считаю, что в java было сделано много оптимизаций. Может, раньше так и надо было, может без этого java не завоевала те позиции, на которых находится сейчас. Но, в итоге, я вижу достаточной сложный язык. Что бы начать программировать на java, на хорошем уровне, надо обязательно почитать JLS, а если хочешь работать с http — пару десятков книг: первая ссылка в рисунках, на Google: ruby vs java, я понимаю что во многом прикол, но доля правды в этом есть.
Доля правды есть. С этим я согласен. Но мне интересно было бы взглянуть на список книг по Ruby через 5-7 лет. Думаю, он увеличится существенно.
Тема интересная, но давайте вернемся к проектированию.
Re[3]: Проектирование: интерфейс vs абстрактный класс
Здравствуйте, malkolinge, Вы писали:
M>Интерфейс необходимо использовать тогда, когда классы различных иерархий должны иметь возможность единообразной работы.
Как один из вариантов, согласен. Но это относится к созданию дизайна. Меня же больше интересует стадия анализа предметной области (Возможно слово "проектирование" в названии темы было выбрано не совсем удачно).
Ситуация проста. Вы приступаете к новой задаче. Вам никак не обойтись без понимания предметной области (домена, etc.). Вы приступаете к ее нанализу. Вы выбираете, какие сущности и связи предметной области важны для вас с точки зрения решаемой задачи. На этом этапе вы уже начинаете поиск кандидатов в классы и интерфейсы.
я написал: Пусть это будет "система поиска работы". job.ru, monster.com. Какие, на ваш взгляд, в этой задаче можно выделить классы и какие интерфейсы? И самое главное — почему?
Анализируем предметную область: Основных требований два. 1. Работник должен найти работу. 2. Работодатель должен найти исполнителя. Конкретнее:
Работник может:
— опубликовать свое резюме (один ко многим).
— поискать вакансии.
— поискать работодателей.
— сохранять выбранную вакансию (один ко многим).
— сравнить две и более вакансий
Работодатель может:
— опубликовать вакансию (один ко многим).
— поискать работника.
— поискать вакансии (оценить привлекательность своей позиции).
— сравнить две и более вакансий
Например, Работник, Резюме и Вакансия у меня были бы кандидатами в классы. На счет Работодателя не уверен. На счет кандидатов в интерфейсы мысле нет.
Надеюсь, вопрос несколько прояснился . Итак, опираясь на данный пример, какие признаки позволяют выделить кандидатов в интерфейсы и кандидатов в классы?
Re[2]: Проектирование: интерфейс vs абстрактный класс
Здравствуйте, TheOldMan, Вы писали:
TOM>Здравствуйте, boluba, Вы писали:
TOM>1. Если реализация может измениться, всегда используйте интерфейсы. При использовании абстрактных классов реализация может фиксироваться
Если бы всегда заранее можно было сказать, какая часть реализации может измениться, было бы проще.
TOM>2. Интерфейсы применяются для описания дополнительных возможностей (Printable, Serializable, Cloneable) TOM>3. Интерфейсы используются в тех случаях, когда реализация по умолчанию не задана. TOM>4. Абстрактные классы используются при частичном определении реализации по умолчанию TOM>5. Иногда интерфейсы могут использоваться в сочетании с абстрактными классами для создания фиксированного интерфейса, комбинируемого с частичной реализацией. Такая комбинация продоставляет удобства частичной реализации с гибкостью интерфейсов.
Все эти советы относяться к проектированию и реализации, нежели к анализу. Возможно, я не точно сформулировал вопрос. Вот здесь
Здравствуйте, lexius, Вы писали:
L>Если очень кратко:
L>абстрактный класс может содержать реализацию.Иногда это удобно.
L>Если приложение правильно проектируется с точки зрения ООП, то очень часто самый первый класс в цепочке наследования — абстрактный. L>Все стальное — в посте выше, там более подробно.
Прощу прощения за расплывчатую формулировку. Вот здесь
Если работа идет с некой "недоменной" областью — то есть technology for technology — то как правило всегда использую только интерфейсы.
Если проектируется часть соотв. некой доменной области — простой подход такой:
Интерфейсы описывают в большей степени свойства объектов, в то время как классы — это is a отношение.
Абстрактный класс Cat это куда сильнее чем некий интерфейс Feedable. Интерфейсы позволяют описать некую общность поведения,
в то время как абстрактные классы это еще и общность состояний и свойств.
wbr,
Igor
Re[2]: Проектирование: интерфейс vs абстрактный класс
Здравствуйте, Pharod, Вы писали:
P>Если работа идет с некой "недоменной" областью — то есть technology for technology — то как правило всегда использую только интерфейсы.
Я встречал в таком виде: "Если задумался над тем, класс это или интерфейс, то это интерфес". Задачи с "недоменной" областью в этом смысле, пожалуй, проще анализировать.
P>Если проектируется часть соотв. некой доменной области — простой подход такой: P>Интерфейсы описывают в большей степени свойства объектов, в то время как классы — это is a отношение. P>Абстрактный класс Cat это куда сильнее чем некий интерфейс Feedable. Интерфейсы позволяют описать некую общность поведения, P>в то время как абстрактные классы это еще и общность состояний и свойств.
Ваши аргументы приняты. Попробую уточнить вопрос.
Классический пример — "простой графический редактор". Идем по классическому пути: редактор работает с фигурами. Треугольник, круг, квадрат. Логично предложить их в качестве кандидатов в классы. Абстрактный класс Фигура тоже выглядить уместным.
Теперь добавим в редактор точку. Точка — это фигура? Или правильнее выделить интерфейсы Drawable, Resizeable, etc?
Как поступить на этапе анализа задачи?
Re[3]: Проектирование: интерфейс vs абстрактный класс
Здравствуйте, boluba, Вы писали:
B>Классический пример
А почему не подходит классическое решение? В данном случая я бы использовал абстарктный класс для создания заглушек под все методы.
Мне интерессно вот чего:
наследование абстрактного класса дороже чем наследование интерфейса ?
Re[3]: Проектирование: интерфейс vs абстрактный класс
B>Классический пример — "простой графический редактор". Идем по классическому пути: редактор работает с фигурами. Треугольник, круг, квадрат. Логично предложить их в качестве кандидатов в классы. Абстрактный класс Фигура тоже выглядить уместным.
B>Теперь добавим в редактор точку. Точка — это фигура? Или правильнее выделить интерфейсы Drawable, Resizeable, etc? B>Как поступить на этапе анализа задачи?
"правильнее" это нехорошее слово — проектирование ради проектирования удел тех, у кого много времени.
если перед вами стоит задача создать графический редактор — оцените требования.
если есть требование, к примеру, поддержать разные predefined фигуры в качестве плагинов — стройте фрэймворк
на интерфейсах, определяйте default behavior с помощью абстрактных имплиментаций.
если просто нужно уметь рисовать точки и три стандартные фигурки, обладающие 100% сходным поведением — думаю
подойдет абстрактный базовый класс вполне. является ли точка фигурой — вопрос сложный. тут опять нужны требования.
можно ли рисовать карандашом? использовать кисти? как раценивать нарисованную юзером карандашом кракозябру?
сильно зависит от того растровый ли это редактор или же векторный.
короче — смотреть детали, оценивать требования, не боятся ошибится. ну заэкстрактите вы потом интерфейсы если
назреет необходимость — чай не конец света :)
извините что так абстрактно отвечаю — но, как говорят, "правильно сформулированный вопрос содержит не менее 80% ответа" :)
и это все сугубо IMHO.
wbr,
Igor
Re[5]: Проектирование: интерфейс vs абстрактный класс
Здравствуйте, boluba, Вы писали:
B>Тут можно спорить. Использование UnsupportedOperationException прямо и подробно описано в документации по Collections Framework. Насколько я понимаю, вы считаете, что раз уж класс реализует интерфейс (контракт), то должен его реализовывать (исполнять) полностью. Но если еще раз подумать, то выброс UnsupportedOperationException является неотемлемой частью контракта в данном контексте, не находите? На ваш взгляд было бы лучше вместо десятка интерфейсов и базовых реализаций иметь сотни конкретных частных решений, не выбрасывающих UnsupportedOperationException?
Я говорю не о конкретной реализации. Возможно тут Джошуа Блох и г-н Моринеску сделали все как посчитали нужным и правильным. Я лишь говорю, что они исказили "нормальность" использования абстрактных классов. По двум причинам.
1. Явно перегрузили методы интерфейса, сделав их абстрактными. (можно было просто ничего не писать и не путать этим следы)
2. Явно "реализовали" методы интерфейса, которые не используются в базовом функционале и реализованы так, что в рантайме (не не в компиляции) говорят о том, что они на самом деле не реализованы.
По этим двум пунктам я и говорил, что Collection Framework является плохим примером Interface -> Abstract Class -> Implementation Class.
Т.е. если абстрактный клас заявляет себя базовым, то он должен:
1. Не трогать методы интерфейса, которые он не собирается реализовывать в базовом варианте.
2. Реализовать методы интерфейса в базовом варианте по возможности с модификатором final!
3. При необходимости дополнения базовой фнкциональности он должен ввести дополнительные абстрактные методы с модификатором protected.
Замечу также, что оставление возможности перегрузки методов интерфейса реализованных в базовом абстрактном классе является также не очень хорошим примером. Потому, что в любой реализации можно изменить базовый функционал таким образом, а он меняться не должен.
Re[3]: Проектирование: интерфейс vs абстрактный класс
Здравствуйте, boluba, Вы писали:
B>Классический пример — "простой графический редактор". Идем по классическому пути: редактор работает с фигурами. Треугольник, круг, квадрат. Логично предложить их в качестве кандидатов в классы. Абстрактный класс Фигура тоже выглядить уместным.
Относительно различий между интерфейсом и абстрактным классом. Ответ: с точки зрения проектирования нет никакой разницы. Различия чисто языковые, т.к. Java и C# не поддерживают множественного наследования.
Здравствуйте, boluba, Вы писали:
B>Могли бы вы ответить на простой вопрос: В каких случаях при проектировании вы делаете выбор в пользу интерфейса, а в каких — в пользу абстрактного класса?
если я правильно интерпретирую канонические книги, то применять нужно всегда интерфейс
за исключением тех случаев, когда без наследования (кроме как большой кровью) не обойтись.
Re[2]: Проектирование: интерфейс vs абстрактный класс
Здравствуйте, mike_sikalo, Вы писали:
_>если я правильно интерпретирую канонические книги, то применять нужно всегда интерфейс _>за исключением тех случаев, когда без наследования (кроме как большой кровью) не обойтись.
У Эккеля так написано в TIJ, если ничего не путаю.
Ветка ушла совсем в сторону от того, что я хотел спросить. Попробую еще раз в новой ветке.