Когда использовать интерфейс вместо абстрактного класса и наоборот?

Попробуйте следующее:

var ipv4 = "212.212.100.110";
var ipv6 = "0000:0000:0000:0000:0000:0000:0000:0001";

//test ipv4

if (/^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$|^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/.test(ipv4)) {

    alert("VALID IPV4 " + ipv4);
} else {
    alert("INVALID IPV4 " + ipv4);
}


//test ipv6  

if (/^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$|^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/.test(ipv6)) {

    alert("VALID IPV6 " + ipv6);
} else {
    alert("INVALID IPV6 " + ipv6);
}

Live demo

ПРИМЕЧАНИЕ: Если вы задаетесь вопросом, оба регулярных выражения равны , они проверяют ipv4 и ipv6

Убедитесь, что вы понимаете, что перед адресом ipv6 address , прежде чем жаловаться на регулярное выражение , не работает .

ИСТОЧНИК: Регулярные выражения Cookbook, 2nd Edition

403
задан Ravindra babu 24 September 2016 в 04:02
поделиться

13 ответов

Я написал статью об этом:

Абстрактные классы и интерфейсы

Суммирование:

, Когда мы говорим об абстрактных классах, мы определяем характеристики типа объекта; определение , что объект .

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

407
ответ дан Jorge Córdoba 24 September 2016 в 14:02
поделиться

Абстрактный класс может иметь реализации.

интерфейс не имеет реализаций, он просто определяет своего рода контракт.

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

0
ответ дан Gerrie Schenck 24 September 2016 в 14:02
поделиться

Это может быть очень трудным вызовом для создания...

Один указатель я могу дать: объект может реализовать много интерфейсов, пока объект может только наследовать один базовый класс (на современном языке OO как c#, я знаю, что C++ имеет множественное наследование - но разве который не осужден?)

0
ответ дан Mesh 24 September 2016 в 14:02
поделиться

Используйте абстрактный класс, если Вы хотите обеспечить некоторые базовые внедрения.

1
ответ дан Sebastian 24 September 2016 в 14:02
поделиться
  • 1
    Большой ответ Dan, Вы могли уточнить то, как Вы отображаете xml узлы на столбцы в таблице? – longhairedsi 9 November 2011 в 03:59

в Java можно наследоваться одному (абстрактному) классу для "обеспечивания" функциональности, и можно реализовать много интерфейсов для "гарантирования" функциональности

1
ответ дан Peter Miehle 24 September 2016 в 14:02
поделиться

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

1
ответ дан Dmitri Nesteruk 24 September 2016 в 14:02
поделиться

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

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

1
ответ дан annakata 24 September 2016 в 14:02
поделиться

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

2
ответ дан Nick Fortescue 24 September 2016 в 14:02
поделиться
  • 1
    Я думаю, что, возможно, понял Ваш ответ:) Я думал, что Вы добавляли xml к столбцу как временное местоположение прежде, чем уничтожить к существующим столбцам таблицы (например, INSERT INTO xxx ОТ XmlFiles. Данные) или такой как. Я искал самый производительный путь к shread xml к существующим столбцам, я думаю с небольшой работой, Ваше решение сделало бы то задание приятно. – longhairedsi 10 November 2011 в 04:37

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

409
ответ дан Alex 24 September 2016 в 14:02
поделиться
  • 1
    Я думаю, что наиболее вероятной причиной исходной проблемы было отсутствие индексов. Если, вместо того, чтобы запросить тот фрагмент XML непосредственно, Вы помещаете его в xml, ввел столбец во временной таблице, определил индекс на том столбце и ЗАТЕМ запросил его, это может иметь большое значение. – Amit Naidu 11 June 2013 в 14:19

Когда сделать то, что является очень простой вещью, если у Вас есть понятие, ясное в Вашем уме.

Абстрактные классы могут быть Получены, тогда как Интерфейсы могут быть Реализованы. Существует некоторое различие между двумя. То, когда Вы получаете Абстрактный класс, отношения между производным классом и базовым классом, 'является' отношениями. например, Собака является Животным, Овца является Животным, что означает, что Производный класс наследовал некоторые свойства от базового класса.

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

я надеюсь, что я ясен.

29
ответ дан Aamir 24 September 2016 в 14:02
поделиться
  • 1
    Интересная информация здесь, но it' s проложенный под землей. Если you' ре все еще о, отправьте это как новый вопрос (и ответьте на него сами, если Вы нашли хорошее решение или определили проблему:-), –  12 January 2011 в 15:41

Лично, у меня почти никогда нет потребности записать абстрактные классы.

Большинство раз я вижу, что абстрактные классы используемый (mis), это - потому что автор абстрактного класса использует "Шаблонный шаблон" метода.

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

(Чрезмерно упрощенный) пример:

abstract class QuickSorter
{
    public void Sort(object[] items)
    {
        // implementation code that somewhere along the way calls:
        bool less = compare(x,y);
        // ... more implementation code
    }
    abstract bool compare(object lhs, object rhs);
}

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

, Таким образом, намеченное использование - что-то вроде этого:

class NameSorter : QuickSorter
{
    public bool compare(object lhs, object rhs)
    {
        // etc.
    }
}

проблема с этим состоит в том, что Вы незаконно связали вместе два понятия:

  1. А способ сравнить два объекта (какой объект должен пойти сначала)
  2. метод А элементов сортировки (т.е. quicksort по сравнению с сортировкой слиянием и т.д.)

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

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

альтернативный метод должен использовать шаблон разработки "Стратегии" вместо этого:

interface IComparator
{
    bool compare(object lhs, object rhs);
}

class QuickSorter
{
    private readonly IComparator comparator;
    public QuickSorter(IComparator comparator)
    {
        this.comparator = comparator;
    }

    public void Sort(object[] items)
    {
        // usual code but call comparator.Compare();
    }
}

class NameComparator : IComparator
{
    bool compare(object lhs, object rhs)
    {
        // same code as before;
    }
}

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

Для "скрытия" того, что мы реализовали "сортировку имен" при помощи класса "QuickSort" и "NameComparator" мы могли бы все еще записать метод фабрики где-нибудь:

ISorter CreateNameSorter()
{
    return new QuickSorter(new NameComparator());
}

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

Одна последняя мысль: Все, что мы сделали выше, "составляют" функцию "NameSorting" при помощи функции "QuickSort" и функции "NameComparison"... на языке функционального программирования, этот стиль программирования становится еще более естественным с меньшим количеством кода.

80
ответ дан Paul Hollingsworth 24 September 2016 в 14:02
поделиться
  • 1
    I' ve, этот одноколейный путь, и я не предложил бы его. Наша самая большая жалоба была то, что Загрузка Объема XML не играла по правилам в транзакционных контекстах. Мы провели слишком много времени, пытаясь заставить это работать, и в конце, it' s часть COM этого это просто isn' t стоящий того. – Didaxis 18 February 2012 в 01:39

Я написал статью того, когда использовать абстрактный класс и когда использовать интерфейс. Существует намного больше различия между ними кроме "одного ISA..., и один CAN - ДЕЛАЮТ...". Мне это - консервированные ответы. Я упоминаю несколько причин, когда использовать любого из них. Надежда это помогает.

http://codeofdoom.com/wordpress/2009/02/12/learn-this-when-to-use-an-abstract-class-and-an-interface/

10
ответ дан 24 September 2016 в 14:02
поделиться
  • 1
    +1 для обеспечения показателя производительности и совместного использования Вашей работы. – Amit Naidu 11 June 2013 в 14:53

OK, having just "grokked" this myself - here it is in layman's terms (feel free to correct me if I am wrong) - I know this topic is oooooold, but someone else might stumble across it one day...

Abstract classes allow you to create a blueprint, and allow you to additionally CONSTRUCT (implement) properties and methods you want ALL its descendants to possess.

An interface on the other hand only allows you to declare that you want properties and/or methods with a given name to exist in all classes that implement it - but doesn't specify how you should implement it. Also, a class can implement MANY interfaces, but can only extend ONE Abstract class. An Interface is more of a high level architectural tool (which becomes clearer if you start to grasp design patterns) - an Abstract has a foot in both camps and can perform some of the dirty work too.

Why use one over the other? The former allows for a more concrete definition of descendants - the latter allows for greater polymorphism. This last point is important to the end user/coder, who can utilise this information to implement the A.P.I(nterface) in a variety of combinations/shapes to suit their needs.

I think this was the "lightbulb" moment for me - think about interfaces less from the author's perpective and more from that of any coder coming later in the chain who is adding implementation to a project, or extending an API.

40
ответ дан 22 November 2019 в 23:30
поделиться
Другие вопросы по тегам:

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