Подтвердить что ты не робот

Разница между интерфейсом и абстрактным классом в терминах развязки?

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

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

  • Мы можем реализовать несколько интерфейсов.

Я только узнал, что мы можем различать их в терминах развязки?

Ваши комментарии...

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

Обычно мы используем Business Logic Layer, Уровень доступа к данным (содержит абстрактные функции) и DataAccess.SqlServer Layer. Правильно? Несмотря на то, что мы знаем о потребностях бизнеса, почему мы создаем Уровень доступа к данным (содержит абстрактные функции), почему не удается Уровень бизнес-логики DataAccess.SqlServer Layer?

4b9b3361

Ответ 1

Развязка

В программировании и дизайне это, как правило, делает код, который можно повторно использовать с минимальным количеством зависимостей.

Factory Шаблон в этом контексте

При использовании шаблона Factory у вас есть централизованный Factory, который может создавать объекты, не определяя их самостоятельно. Это зависит от определения объекта.

Аннотация и интерфейс

Интерфейс

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

Абстрактный

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

Edit

Объяснение

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

Развязка

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

Пример

Определение интерфейса

public interface IReady
{
    bool ComputeReadiness();
}

Наследование

public abstract class WidgetExample : IReady
{
    public int WidgetCount { get; set; }
    public int WidgetTarget { get; set; }
    public bool WidgetsReady { get; set; }

    public WidgetExample()
    {
        WidgetCount = 3;
        WidgetTarget = 45;
    }

    public bool ComputeReadiness()
    {
        if (WidgetCount < WidgetTarget)
        {
            WidgetsReady = false;
        }
        return WidgetsReady;
    }
}


public class Foo : WidgetExample
{
    public Foo()
    {
        this.WidgetTarget = 2;
    }
}

public class Bar : IReady
{
    public bool ComputeReadiness()
    {
        return true;
    }
}

Развязка

public class UsesIReady
{
    public bool Start { get; set; }
    public List<string> WidgetNames { get; set; }

    //Here is the decoupling. Note that any object passed
    //in with type IReady will be accepted in this method
    public void BeginWork(IReady readiness)
    {
        if (readiness.ComputeReadiness())
        {
            Start = true;
            Work();
        }
    }

    private void Work()
    {
        foreach( var name in WidgetNames )
        {
            //todo: build name
        }
    }
}

Полиморфизм

public class Main
{
    public Main()
    {
        //Notice that either one of these implementations 
        //is accepted by BeginWork

        //Foo uses the abstract class
        IReady example = new Foo();
        UsesIReady workExample = new UsesIReady();
        workExample.BeginWork(example);

        //Bar uses the interface
        IReady sample = new Bar();
        UsesIReady workSample = new UsesIReady();
        workSample.BeginWork(sample);
    }
}

Ответ 2

Я просматривал ответы, и все они кажутся немного сложными для вопроса. Итак, вот мой (надеюсь) более простой ответ.

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

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

  • Всегда используйте Интерфейсы, чтобы определить внешнее поведение.
  • Если у вас есть некоторые версии детали, используйте абстрактные классы, чтобы определить их, но реализовать интерфейсы на абстрактные классы и наследуют от этих классов по очереди.

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

EDIT: я забыл включить ссылку:) http://www.codeproject.com/Articles/11155/Abstract-Class-versus-Interface

Ответ 3

Абстрактные классы и интерфейсы не являются ВЗАИМНО ЭКСКЛЮЗИВНЫМИ вариантами. Я часто определяю как интерфейс, так и абстрактный класс, реализующий этот интерфейс.

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

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

Ответ 4

Развязка ради развязки - бесполезное упражнение.

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

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

public interface IHasQuantity { double Quantity { get; } }
public interface IHasPrice { decimal PricePerUnit { get; } }

public static class TraitExtensions
{
    public static decimal CalculateTotalPrice<T>(this T instance)
        where T : class, IHasPrice, IHasQuantity
    {
        return (decimal)instance.Quantity * instance.PricePerQuantity;
    }
}

На мой взгляд, абстрактные классы и наследование классов злоупотребляют.

СОЛИДНЫЕ принципы проектирования обучают нас тому, что принцип подписи Лискова подразумевает, что наследование класса следует использовать только в том случае, если унаследованный класс подменяется для предка. Это означает, что все методы должны быть реализованы (не бросайте новый NotImplementedExeption()) и должны вести себя так, как ожидалось.

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

Теперь вернемся к вашему вопросу; интерфейсы должны использоваться больше всего, если не все время. Наследование классов должно использоваться внутренне и только внешне для целей определения, после чего интерфейс должен использоваться для взаимодействия и конкретной реализации, предоставляемой через factory, или для инъекции через контейнер IOC.

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

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

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

Ответ 5

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

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

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

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

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

Ответ 6

Основное различие заключается в следующем:

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

  • Абстрактные классы выставляют нулевые или более полные методы, которые потомки могут использовать или переопределять, обеспечивая их собственную реализацию. Этот подход позволяет определить настраиваемое поведение по умолчанию. Абстрактные классы позволяют легко добавлять новые методы без проблем (NotImplementedException действительно сияет при добавлении методов к абстрактным классам), тогда как добавление метода к интерфейсу требует изменения всех классов, реализующих его.

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

  • Жесткий диск, который обеспечивает как USB, так и LAN-порты, является хорошей демонстрацией наследования нескольких интерфейсов.
  • Ноутбук со светодиодной маркировкой "bluetooth", но нет оборудования Bluetooth на борту, является хорошей аналогией концепции не реализации абстрактного метода (у вас есть светодиод, у вас есть маленький символ B, но нет ничего под крыша).

Изменить 1

Здесь ссылка MSDN, объясняющая, как выбирать между интерфейсом и классами.

Ответ 7

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

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

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

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

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

Ответ 8

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

  • Вы не можете создать абстрактный класс
  • У вас может быть абстрактный метод только в абстрактном классе

Ответ 9

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

public interface Polymorphism{
void run();
Void Bark();
Energy getEnergy(Polymorphism test);
Public abstract class EnergySynthesis implements Polymorphism{
abstract void Energy();
Void Bark(){
 getEnergy(){

}
void run(){
getEnergy();

}public EnegyGeneartion extends EnergySynthesis  {
Energy getEnergy(Polymorphism test){
return new Energy( test); 
}
MainClass{

EnegyGeneartion test=new EnegyGeneartion ();
test.getEnergy(test);
test.Bark()
.
.
.
.
.
//here in Energy getEnergy(Polymorphism test) any class can be passed as parameter that implemets interface