Интерфейс против Базового класса

Слайс Scape просто используется \ перед /, и он будет экранирован. (\/ => /).

В противном случае вы можете использовать следующее выражение: DD / MM / YYYY:

/^[0-9]{2}[\/]{1}[0-9]{2}[\/]{1}[0-9]{4}$/g

Пояснение :

  • [0-9]: Just Numbers
  • {2} или {4}: длина 2 или 4. Вы можете сделать {2,4} также длину между двумя числами (2 и 4 в этом случае)
  • [\/]: Символ /
  • g: Глобальный - или m: Многострочный (дополнительно, см. Ваши запросы)
  • $: привязка к концу строки. (Необязательно, см. Ваши пожелания)
  • ^: начало строки. (Необязательно, см. Ваши пожелания)

Пример использования:

var regex = /^[0-9]{2}[\/][0-9]{2}[\/][0-9]{4}$/g;

var dates = ["2009-10-09", "2009.10.09", "2009/10/09", "200910-09", "1990/10/09", 
    "2016/0/09", "2017/10/09", "2016/09/09", "20/09/2016", "21/09/2016", "22/09/2016",
    "23/09/2016", "19/09/2016", "18/09/2016", "25/09/2016", "21/09/2018"];

//Iterate array
dates.forEach(
    function(date){
        console.log(date + " matches with regex?");
      console.log(regex.test(date));
    });

Конечно, вы может использоваться как boolean:

if(regex.test(date)){
     //do something
}
746
задан 6 revs, 6 users 100% 6 March 2016 в 21:25
поделиться

29 ответов

Давайте возьмем Ваш пример Собаки и класса CAT, и давайте проиллюстрируем использование C#:

И собака и кошка являются животными, а именно, млекопитающие четвероногого животного (животные waaay слишком общий). Давайте предположим, что у Вас есть Млекопитающее абстрактного класса для них обоих:

public abstract class Mammal

Этот базовый класс будет, вероятно, иметь методы по умолчанию, такие как:

  • Канал
  • Помощник

, Все из которых являются поведением, которые имеют более или менее ту же реализацию между любой разновидностью. Для определения этого, Вы будете иметь:

public class Dog : Mammal
public class Cat : Mammal

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

public class Giraffe : Mammal
public class Rhinoceros : Mammal
public class Hippopotamus : Mammal

Это все еще будет допустимо, потому что в ядре функциональности Feed() и Mate() все еще будет то же.

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

public interface IPettable
{
    IList<Trick> Tricks{get; set;}
    void Bathe();
    void Train(Trick t);
}

реализация для вышеупомянутого контракта не будет тем же между кошкой и собакой; помещение их реализаций в абстрактном классе для наследования будет плохой идеей.

Ваша Собака и определения CAT должны теперь быть похожими:

public class Dog : Mammal, IPettable
public class Cat : Mammal, IPettable

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

, Следовательно, потому что можно обычно только наследоваться одному абстрактному классу (на большинстве языков OO со статическим контролем типов, который является... исключениями, включают C++), но быть в состоянии реализовать несколько интерфейсов, это позволяет Вам создавать объекты в строго как требуется основание.

484
ответ дан 8 revs, 5 users 94% 6 March 2016 в 21:25
поделиться

Это зависит от Ваших требований. Если бы IPet достаточно прост, я предпочел бы реализовывать это. Иначе, если PetBase реализует тонну функциональности, Вы не хотите копировать, затем имеете в нем.

оборотная сторона к реализации базового класса является требованием к override (или new) существующие методы. Это делает их виртуальными методами, что означает, что необходимо быть осторожны относительно того, как Вы используете экземпляр объекта.

Наконец, единичное наследование.NET уничтожает меня. Наивный пример: Скажите создание пользовательского элемента управления таким образом, Вы наследовались UserControl. Но, теперь Вы заблокированы из также наследования PetBase. Это вынуждает Вас реорганизовать, например, для создания PetBase участник класса, вместо этого.

2
ответ дан spoulson 6 March 2016 в 21:25
поделиться

@Joel: Некоторые языки (например, C++) позволяют множественное наследование.

2
ответ дан Einar 6 March 2016 в 21:25
поделиться

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

2
ответ дан Bill the Lizard 6 March 2016 в 21:25
поделиться

Наследник базового класса должен иметь, "" отношения. Интерфейс представляет "реализации" отношения. Поэтому только используйте базовый класс, когда Ваши наследники поддержат отношений.

1
ответ дан Aaron Fischer 6 March 2016 в 21:25
поделиться

В дополнение к тем комментариям, которые упоминают реализацию IPet/PetBase, существуют также случаи, где обеспечение класса помощника средства доступа может быть очень ценным.

стиль IPet/PetBase предполагает, что у Вас есть несколько реализаций, таким образом увеличивающих стоимость PetBase, так как это упрощает реализацию. Однако, если у Вас есть реверс или смешение двух, где у Вас есть несколько клиентов, обеспечивание справки класса помочь в использовании интерфейса может уменьшить стоивший, облегчив использовать интерфейс.

0
ответ дан Torlack 6 March 2016 в 21:25
поделиться

Используйте свое собственное решение и будьте умны. Не всегда делайте то, что говорят другие (как я). Вы услышите, "предпочитают интерфейсы абстрактным классам", но это действительно зависит. Это зависит, каков класс.

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

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

Также рассматривают это, как поддерживать Ваши абстракции со временем. Интерфейсы фиксируются: Вы выпускаете интерфейс как контракт для ряда функциональности, которую может реализовать любой тип. Базовые классы могут расширяться со временем. Те расширения становятся частью каждого производного класса.

0
ответ дан David Pokluda 6 March 2016 в 21:25
поделиться

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

Это работает особенно хорошо в моем поле: игровое программирование. Базовые классы могут быть чрезмерно увеличены в размере с тоннами поведений, которые "могут" быть необходимы наследованным объектам. С интерфейсами различные поведения могут быть добавлены или удалены к объектам легко и с готовностью. Например, если я создаю интерфейс для "IDamageEffects" для объектов, что я хочу отразить повреждение, тогда я могу легко применить это к различным игровым объектам, и легко передумать позже. Скажите, что я разрабатываю начальный класс, который я хочу использовать для "статических" декоративных объектов, и я первоначально решаю, что они ненепрочны. Позже, я могу решить, что это представило бы больший интерес, если они могли бы аварийно завершиться так, я изменяю класс для реализации интерфейса "IDamageEffects". Это намного легче сделать, чем переключение базовых классов или создание новой иерархии объектов.

0
ответ дан Mark 6 March 2016 в 21:25
поделиться

Существуют другие преимущества для наследования также - такие как способность к переменной, чтобы быть в состоянии содержать объект или родительского класса или наследованного класса (не имея необходимость объявлять его как что-то универсальное, как "Объект").

, Например, в.NET WinForms, большинство компонентов UI происходит из Системы. Windows. Формы. Управление, таким образом, переменная объявила, поскольку это могло "содержать" примерно какой-либо элемент UI - действительно ли это быть кнопкой, ListView, или что имеет Вас. Теперь, предоставленный, у Вас не будет доступа ко всем свойствам или методам объекта, но у Вас будет весь основной материал - и это может быть полезно.

0
ответ дан Keithius 6 March 2016 в 21:25
поделиться

Необходимо использовать базовый класс, если действительно нет никакой причины для других разработчиков требовать использовать их собственный базовый класс в дополнение к участникам типа , и Вы предвидите проблемы управления версиями (см. http://haacked.com/archive/2008/02/21/versioning-issues-with-abstract-base-classes-and-interfaces.aspx ).

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

0
ответ дан Mark Cidade 6 March 2016 в 21:25
поделиться

Не используйте базовый класс, если Вы не знаете то, что это означает, и что это применяется в этом случае. Если это применяется, используйте его, иначе, интерфейсы использования. Но отметьте ответ о маленьких интерфейсах.

Общедоступное Наследование злоупотребляется в OOD и выражает намного больше, чем большинство разработчиков понимает или готово соответствовать. Посмотрите Принцип Liskov Substitutablity

Короче говоря, если "" B тогда A, требует не больше, чем B и поставляет не меньше, чем B, для каждого метода, который он представляет.

3
ответ дан theschmitzer 6 March 2016 в 21:25
поделиться

Ну, Josh Bloch сказал себя в Эффективный Java, 2-й :

Предпочитают интерфейсы по абстрактным классам

Некоторые основные моменты:

  • Существующие классы могут быть легко модифицированы для реализации нового интерфейса . Все, что необходимо сделать, добавляют требуемые методы, если они don’t уже существуют и добавляют пункт реализаций к объявлению класса.

  • Интерфейсы идеальны для определения mixins. Свободно говоря, смешивание является типом, который класс может реализовать в дополнение к его “primary type”, чтобы объявить, что это обеспечивает некоторое дополнительное поведение. Например, Сопоставимый смесительный интерфейс, который позволяет классу объявлять, что его экземпляры заказаны относительно других взаимно сопоставимых объектов.

  • Интерфейсы позволяют конструкцию неиерархических платформ типа . Иерархии типа являются большими для организации некоторых вещей, но другие вещи don’t аккуратно попадают в твердую иерархию.

  • Интерфейсы включают безопасные, мощные улучшения функциональности через обертку - на идиому класса. При использовании абстрактных классов для определения типов, Вы оставляете программиста, который хочет добавить функциональность без альтернативы, но использовать наследование.

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

, С другой стороны, интерфейсы очень трудно развить. Если Вы добавите метод к интерфейсу, то это повредит весь, его - реализации.

пз.: Купите книгу. Это намного более подробно.

139
ответ дан 5 revs, 3 users 97% 6 March 2016 в 21:25
поделиться

Концептуально, Интерфейс привык к официально, и полуофициально определите ряд методов, которые предоставит объект. Официально средства ряд имен методов и подписей, полуофициально человекочитаемая документация средств, связанная с теми методами. Интерфейсы являются только описаниями API (в конце концов, API поддерживает Прикладного программиста Интерфейс ), они не могут содержать реализацию, и не возможно использовать или выполнить Интерфейс. Они только делают явными контракт того, как необходимо взаимодействовать с объектом.

Классы обеспечивают реализацию, они могут объявить, что реализуют нуль, один или несколько Интерфейсов. Если Класс предназначается, чтобы быть наследованным, соглашение состоит в том, чтобы снабдить префиксом Имя класса "Основу".

существует различие между Базовым классом и Абстрактные базовые классы (ABC). ABC смешивают интерфейс и реализацию вместе. Краткий обзор за пределами программирования означает "сводку", которая является "Кратким обзором == Интерфейс". Абстрактный базовый класс может тогда описать обоих интерфейс, а также пустое, частичное или полноценное внедрение, которое предназначается, чтобы быть наследованным.

Мнения о том, когда использовать Интерфейсы по сравнению с Абстрактными базовыми классами по сравнению только с Классами, собираются варьироваться дико и на основе того, что Вы разрабатываете, и в каком языке Вы разрабатываете. Интерфейсы часто связываются только со статически типизированными языками, такими как Java или C#, но динамически типизированные языки могут также иметь Интерфейсы и Абстрактные базовые классы. В Python, например, различие ясно дано понять между Классом, который объявляет, что это реализации Интерфейс и объект, который является экземпляром Класса, и сказан , обеспечивают тот Интерфейс. Возможно на динамическом языке, что два объекта, которые являются оба экземплярами того же Класса, могут объявить, что обеспечивают полностью отличающийся интерфейсы. В Python это только возможно для атрибутов объектов, в то время как методы являются общим состоянием между всеми объектами Класса. Однако в Ruby, объекты могут иметь на методы экземпляра, таким образом, возможно, что Интерфейс между двумя объектами того же Класса может варьироваться так же, как программист требует (однако, Ruby не имеет никакого явного способа объявить Интерфейсы).

На динамических языках Интерфейс к объекту часто неявно принимается, любой путем анализирования объекта и выяснения у него, какие методы это обеспечивает (Взгляд Прежде чем Вы Прыжок) или предпочтительно путем простой попытки использовать желаемый Интерфейс на объекте и ловли исключений, если объект не обеспечивает тот Интерфейс (Легче Спросить Прощение, чем Разрешение). Это может привести к "ложным положительным сторонам", где два Интерфейса имеют то же имя метода, но семантически отличаются, однако компромисс - то, что Ваш код более гибок, так как Вы не должны, определяют заранее для предупреждения всех возможных применений кода.

3
ответ дан Wheat 6 March 2016 в 21:25
поделиться

Современный стиль должен определить IPet и PetBase.

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

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

110
ответ дан 2 revs 6 March 2016 в 21:25
поделиться

Интерфейсы и базовые классы представляют два различных форм отношений.

Наследование (базовые классы) представляет, "-" отношения. Например, собака или кошка "-" домашнее животное. Эти отношения всегда представляют (сингл) цель из класса (в сочетании с "единственный принцип ответственности" ).

Интерфейсы , с другой стороны, представляют дополнительные функции из класса. Я звонил бы, это "являются" отношения, как в" Foo доступно", следовательно эти IDisposable интерфейс в C#.

108
ответ дан 3 revs 6 March 2016 в 21:25
поделиться

Интерфейсы

  • Определяют контракт между 2 модулями. Не может иметь никакой реализации.
  • Большинство языков позволяет Вам реализовывать несколько интерфейсов
  • , Изменение интерфейса является повреждающимся изменением. Все реализации должны быть перекомпилированы/изменены.
  • Все участники общедоступны. Реализации должны реализовать всех участников.
  • Интерфейсы помогают в Разъединении. Можно использовать ложные платформы для насмешки чего-либо позади интерфейса
  • , Интерфейсы обычно указывают на своего рода поведение
  • , Интерфейсные реализации разъединяются / изолированный друг от друга

, Базовые классы

  • Позволяют Вам добавлять [приблизительно 1 116] значение по умолчанию реализация, которую Вы получаете бесплатно деривацией
  • Кроме C++, можно только произойти из одного класса. Даже если мог от нескольких классов, это обычно - плохая идея.
  • Изменение базового класса относительно легко. Деривации не должны делать ничего специального
  • , Базовые классы могут объявить защищенные и государственные функции, к которым могут получить доступ деривации
  • , Абстрактные базовые классы нельзя дразнить легко как интерфейсы
  • , Базовые классы обычно указывают на иерархию типа (A)
  • , деривации Класса могут произойти для зависимости от некоторого основного поведения (имейте сложное знание родительской реализации). Вещи могут быть грязными, если Вы вносите изменение в базовое внедрение для одного парня и повреждаете другие.
62
ответ дан 2 revs, 2 users 97% 6 March 2016 в 21:25
поделиться

В целом необходимо одобрить интерфейсы по абстрактным классам. Одна причина использовать абстрактный класс состоит в том, если у Вас есть общая реализация среди реальных классов. Конечно, необходимо все еще объявить интерфейс (IPet) и иметь абстрактный класс (PetBase) реализация тот интерфейс. Используя маленькие, отличные интерфейсы, можно использовать кратные числа для дальнейшего улучшения гибкости. Интерфейсы позволяют максимальное количество гибкости и мобильность типов через границы. Когда передающие ссылки через границы, всегда передавайте интерфейс а не конкретный тип. Это позволяет принимающему концу определять конкретную реализацию и обеспечивает максимальную гибкость. Это абсолютно верно при программировании способом TDD/BDD.

Банда Четырех указанных в их книге, "Поскольку наследование представляет подкласс деталям реализации его родителя, часто говорится, что 'наследование повреждает инкапсуляцию". Я полагаю, что это верно.

57
ответ дан 5 revs 6 March 2016 в 21:25
поделиться

Другая опция иметь в виду использует, "имеет -" отношения, иначе "реализованы с точки зрения" или "состав". Иногда это - инструмент для очистки, более гибкий способ структурировать вещи, чем использование "-" наследование.

Это не может иметь столько же смысла логически, чтобы сказать, что у Собаки и CAT оба "есть" Домашнее животное, но это избегает ловушек наследования общего множителя:

public class Pet
{
    void Bathe();
    void Train(Trick t);
}

public class Dog
{
    private Pet pet;

    public void Bathe() { pet.Bathe(); }
    public void Train(Trick t) { pet.Train(t); }
}

public class Cat
{
    private Pet pet;

    public void Bathe() { pet.Bathe(); }
    public void Train(Trick t) { pet.Train(t); }
}

Да, этот пример показывает, что существует много дублирования кода и отсутствие элегантности, вовлеченной в выполнение вещей этот путь. Но нужно также ценить, что это помогает сохранить Собаку и CAT разъединенными от Любимого класса (у той Собаки, и CAT не имеют доступа к членам парламента, не занимающим официального поста Домашнего животного), и это оставляет комнату для Собаки и CAT для наследования чему-то еще - возможно класс Млекопитающего.

Состав предпочтителен, когда никакой частный доступ не требуется, и Вы не должны обращаться к Собаке и CAT с помощью универсальных Любимых ссылок/указателей. Интерфейсы дают Вам, что возможность общей ссылки и может помочь сократить многословие Вашего кода, но они могут также запутать вещи, когда они плохо организованы. Наследование полезно, когда Вам нужен доступ члена парламента, не занимающего официального поста, и в использовании его Вы фиксируете себя высокой связи Вашей Собаки и классов CAT к Вашему Любимому классу, который является крутой стоимостью для платы.

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

3
ответ дан 2 revs 6 March 2016 в 21:25
поделиться

Это - симпатичная конкретная.NET, но книга Руководства по проектированию Платформы утверждает, что в общих классах дают больше гибкости в развивающейся платформе. Как только интерфейс поставляется, Вы не получаете шанс изменить его, не повреждая код, который использовал тот интерфейс. С классом однако, можно изменить его и не повредить код, который связывается с ним. Поскольку долго Вы делаете правильные модификации, который включает добавляющую новую функциональность, Вы будете в состоянии расширить и развить Ваш код.

Krzysztof Cwalina говорит на странице 81:

В течение трех версий Платформы.NET, я говорил об этой инструкции с довольно многими разработчиками в нашей команде. Многие из них, включая тех, кто первоначально не согласился с инструкциями, сказали, что они сожалеют поставлявший некоторый API как интерфейс. Я не услышал о даже одном случае, в котором кто-то сожалел, что они поставили класс.

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

48
ответ дан fryguybob 6 March 2016 в 21:25
поделиться

Предыдущие комментарии об использовании абстрактных классов для общей реализации находятся определенно на метке. Одно преимущество, которое я не видел упомянутый еще, - то, что использование интерфейсов делает намного легче реализовать фиктивные объекты в целях поблочного тестирования. При определении IPet и PetBase, поскольку Jason Cohen описал, позволяет Вам дразнить различные условия данных легко, без издержек физической базы данных (пока Вы не решаете, что пора протестировать реальную вещь).

3
ответ дан Scott Lawrence 6 March 2016 в 21:25
поделиться

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

В некоторых случаях, можно найти, что основным объектам не нужны интерфейсы вообще, если все изменяемое поведение определяется в объектах помощника.

Так вместо IPet или PetBase, Вы могли бы закончить с Домашним животным, которое имеет параметр IFurBehavior. Параметр IFurBehavior устанавливается CreateDog () метод PetFactory. Именно этот параметр называют для сарая () методом.

, Если Вы делаете это, Вы найдете, что Ваш код намного более гибок и большая часть Вашего соглашения о простых объектах с очень простыми поведениями в масштабе всей системы.

я рекомендую этот шаблон даже на нескольких-inheritence языков.

12
ответ дан Joe 6 March 2016 в 21:25
поделиться

Вот основное и простое определение интерфейсного и базового класса:

  • Базовый класс = возражают наследованию.
  • Интерфейс = функциональное наследование.

аплодисменты

16
ответ дан 2 revs, 2 users 77% 6 March 2016 в 21:25
поделиться

Juan,

мне нравится думать об интерфейсах как о способе характеризовать класс. Конкретный класс породы собак, скажем YorkshireTerrier, может быть убывавшим из родительского класса собаки, но это - также реализации IFurry, IStubby и IYippieDog. Таким образом, класс определяет то, что класс является всего лишь интерфейсом, говорит нам вещи об этом.

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

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

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

Поэтому, если бы Вы думаете как я, что определенно сказали бы, что CAT и Собака являются IPettable. Это - характеристика, которая соответствует им обоим.

другая часть этого, хотя, у них должен быть тот же базовый класс? Вопрос, делают их нужно широко рассматривать как то же самое. Конечно, они - оба Животные, но делает то соответствие, как мы собираемся использовать их вместе.

Говорят, что я хочу собрать все классы Животных и поместить их в мой контейнер Ковчега.

Или они должны быть Млекопитающими? Возможно, нам нужно некоторое перекрестное животное, доящее фабрику?

они должны даже быть соединены вообще? Достаточно просто знать, что они - оба IPettable?

я часто чувствую требование получить целую иерархию классов, когда мне действительно просто нужен один класс. Я делаю это в ожидании когда-нибудь, мне, возможно, понадобился бы он, и обычно я никогда не делаю. Даже когда я делаю, я обычно нахожу, что должен сделать много для фиксации его. That’s, потому что первый класс я создаю, не является Собакой, я не настолько удачлив, это - вместо этого Утконос. Теперь моя вся иерархия классов основана на причудливом случае, и у меня есть много потраченного впустую кода.

Вы могли бы также найти в какой-то момент, что не все Кошки являются IPettable (как этот лысый). Теперь можно переместить тот Интерфейс во все производные классы то соответствие. Вы найдете, что намного меньше повреждающегося изменения, что внезапно Кошки больше не получаются из PettableBase.

19
ответ дан Flory 6 March 2016 в 21:25
поделиться

Также имейте в виду, чтобы не быть отметенными в OO (, видят блог ), и всегда объекты модели на основе требуемого поведения, если бы Вы разрабатывали приложение, где единственное поведение, которого Вы потребовали, было родовым названием и разновидностями для животного тогда, то Вам только был бы нужен один класс Животное со свойством для имени вместо миллионов классов для каждого возможного животного в мире.

10
ответ дан 2 revs, 2 users 80% 6 March 2016 в 21:25
поделиться

Интерфейсы должны быть маленькими. Действительно маленький. Если Вы действительно сломаете свои объекты, то Ваши интерфейсы будут, вероятно, только содержать несколько очень определенных методов и свойств.

Абстрактные классы являются ярлыками. Есть ли вещи, что все производные доли PetBase, которую можно кодировать однажды и быть сделаны с? Если да, то время для абстрактного класса.

Абстрактные классы также ограничивают. В то время как они дают Вам большой ярлык на создание дочерних объектов, любой данный объект может только реализовать один абстрактный класс. Много раз я нахожу это ограничением Абстрактных классов, и это - то, почему я использую много интерфейсов.

Абстрактные классы могут содержать несколько интерфейсов. Ваш абстрактный класс PetBase может реализовать IPet (у домашних животных есть владельцы), и IDigestion (домашние животные едят, или по крайней мере они должны). Однако PetBase, вероятно, не реализует IMammal, с тех пор не, все домашние животные являются млекопитающими, и не все млекопитающие домашние животные. Можно добавить MammalPetBase, который расширяет PetBase, и добавьте IMammal. FishBase мог иметь PetBase и добавить IFish. IFish имел бы ISwim и IUnderwaterBreather как интерфейсы.

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

7
ответ дан Jarrett Meyer 6 March 2016 в 21:25
поделиться

Случай для Базовых классов по Интерфейсам был объяснен хорошо в Подосновных Инструкциях по Кодированию.NET:

Базовые классы по сравнению с Интерфейсами интерфейсный тип является частичным описанием значения, потенциально поддерживаемого многими типами объектов. Используйте базовые классы вместо интерфейсов, когда это возможно. С точки зрения управления версиями классы более гибки, чем интерфейсы. С классом можно поставить Версию 1.0, и затем в Версии 2.0 добавляют новый метод к классу. Пока метод не абстрактен, любые существующие производные классы продолжают функционировать неизменные.

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

  1. Несколько несвязанных классов хотят поддерживать протокол.
  2. Эти классы уже установили базовые классы (например, некоторые - средства управления пользовательским интерфейсом (UI), и некоторые - веб-сервисы XML).
  3. Агрегирование не является соответствующим или реальным. Во всех других ситуациях наследование классов является лучшей моделью.
6
ответ дан YeahStu 6 March 2016 в 21:25
поделиться

Одно важное различие - то, что можно только наследоваться один базовый класс, но можно реализовать многие интерфейсы. Таким образом, Вы только хотите использовать базовый класс, если Вы абсолютно уверены , что Вы не должны будете также наследовать различный базовый класс. Кроме того, если Вы находите, что Ваш интерфейс становится большим тогда, необходимо начать надеяться разбивать его в несколько логических частей, которые определяют независимую функциональность, так как нет никакого правила, что класс не может реализовать их всех (или что можно определить различный интерфейс, который просто наследовал их всех для группировки их).

5
ответ дан 2 revs 6 March 2016 в 21:25
поделиться

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

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

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

Поведения должны присваиваться сначала интерфейсам (включая интерфейс по умолчанию класса) и способствоваться базовому классу, только если они (a) характерный для большой группы классов, которые являются подмножествами большего класса - в том же смысле, что "кошка" и "человек" являются подмножествами "млекопитающего".

выгода после понимания объектно-ориентированного дизайна достаточно лучше, чем я сделал сначала, Вы будете обычно делать это автоматически, даже не думая об этом. Так пустая истина оператора "код к интерфейсу, не абстрактный класс" становится настолько очевидным, что Вам нелегко полагать, что любой потрудился бы говорить это - и начинать пытаться считать другие значения в него.

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

4
ответ дан Don Edwards 6 March 2016 в 21:25
поделиться

Объясненный хорошо в этом статья

Java World Лично я склонен использовать интерфейсы для определения интерфейсов - т.е. части проектирования системы, которые определяют, как к чему-то нужно получить доступ.

весьма распространено, что у меня будет класс, реализовывая 1 или более интерфейсов.

Абстрактные классы я использую в качестве основания для чего-то еще.

следующее является выпиской из вышеупомянутой статьи JavaWorld.com статьи , автора Tony Sintes, <час> 04/20/01

, Интерфейс по сравнению с интерфейсами Выбора абстрактного класса

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

Абстрактные классы позволяют Вам определить некоторые поведения; они вынуждают Ваши подклассы предоставить другим. Например, если у Вас есть среда разработки приложения, абстрактный класс может предоставить услуги по умолчанию, такие как обработка событий и обработка сообщений. Те сервисы позволяют Вашему приложению включать к Вашей среде разработки приложения. Однако существует некоторая специализированная функциональность, которую только может выполнить Ваше приложение. Такая функциональность могла бы включать запуск и завершить работу задач, которые являются часто зависящими от приложения. Таким образом вместо того, чтобы пытаться определить то поведение само, абстрактный базовый класс может объявить абстрактное завершение работы и запустить методы. Базовый класс знает, что ему нужны те методы, но абстрактный класс позволяет Вашему классу признать, что он не знает, как выполнить те действия; это только знает, что должно инициировать действия. Когда пора запустить, абстрактный класс может назвать метод запуска. Когда базовый класс называет этот метод, Java называет метод определенным дочерним классом.

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

Класс по сравнению с интерфейсом

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

, Например, Стратегическая модель позволяет Вам подкачать новые алгоритмы и процессы в Вашу программу, не изменяя объекты, которые используют их. Медиаплеер мог бы знать, как играть CD, MP3s и wav файлы. Конечно, Вы не хотите к hardcode те алгоритмы воспроизведения в плеер; это будет мешать добавлять новый формат как AVI. Кроме того, Ваш код будет замусорен бесполезными операторами выбора. И добавить оскорбление травмы, необходимо будет обновить те операторы выбора каждый раз, когда Вы добавляете новый алгоритм. В целом, это не очень объектно-ориентированный способ программировать.

Со Стратегической моделью, можно просто инкапсулировать алгоритм позади объекта. Если Вы делаете это, можно обеспечить новые плагины медиа в любое время. Давайте назовем сменный класс MediaStrategy. Тот объект имел бы один метод: playStream (Поток s). Таким образом для добавления нового алгоритма мы просто расширяем наш класс алгоритма. Теперь, когда программа встречается с новым типом среды, она просто делегирует игру потока к нашей стратегии медиа. Конечно, Вам будет нужна некоторая инфраструктура для надлежащего инстанцирования стратегий алгоритма, в которых Вы будете нуждаться.

Это - превосходное место для использования интерфейса. Мы использовали Стратегическую модель, которая ясно указывает на место в дизайне, который изменится. Таким образом необходимо определить стратегию как интерфейс. Необходимо обычно одобрять интерфейсы по наследованию, когда Вы хотите объект иметь определенный тип; в этом случае, MediaStrategy. Доверие наследованию для идентификационных данных типа опасно; это блокирует Вас в конкретную иерархию наследования. Java не позволяет множественное наследование, таким образом, Вы не можете расширить что-то, что дает Вам полезную реализацию или больше идентификационных данных типа.

12
ответ дан Richard Harrison 6 March 2016 в 21:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: