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

Наследование по сравнению с интерфейсом в С#

Возможные дубликаты:
Интерфейс против базового класса
Когда следует выбирать наследование над интерфейсом при разработке библиотек классов С#?

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

class Scraper
{
    string scrapeDate(url);
    string scrapeTime(url);
    //&c.
}

Тогда у меня будет четыре класса, которые наследуют от него.

Другой вариант - сделать Scraper интерфейс и реализовать его четыре класса.

Каковы различия между этими подходами?

4b9b3361

Ответ 1

Наследование классов представляет собой отношение "is-a", например, a Tank является Vehicle. Если ваша ситуация, по крайней мере, не соответствует этому, выберите интерфейс по наследованию.

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

В С# вы можете наследовать только один класс, но несколько интерфейсов. Это будет еще одной причиной выбора интерфейса над наследованием.

Получите идею?

Ответ 2

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

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

Например: в одном приложении мой уровень доступа к данным строится вокруг классов "поставщик", которые изолируют бизнес-объекты и объекты прокси-сервера базы данных от базы данных. В одном случае у меня есть провайдер, который взаимодействует с базой данных SQL Server, а другой - для связи с Oracle CRM On Demand (иначе, почему Бог Почему). Оба реализуют агностический интерфейс, так что клиентский код не заботится о том, какие данные хранятся в нем, или о причудах работы с каждым.

Поставщик Oracle взаимодействует с размещенным сервером через набор веб-сервисов, управляет сеансами связи, запросами пакетов и т.д. Поставщик SQL использует набор хранимых процедур. Хотя оба интерфейса допускают одни и те же классы данных, поставщик Oracle преобразует данные в соответствии с их эзотерической (если не сказать легко) схемой. С помощью этой реализации я мог бы легко добавить поставщика для использования хранилища данных XML, другой СУРБД или заглушки/макета unit test.

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

Ответ 3

Честно говоря, сделайте оба.

public interface IScraper
{
  string ScrapeDate(string url);
}

public abstract class Scraper : IScraper
{
  public string ScrapeDate(string url)
  {
    // default implementation
  }
}

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

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

Ответ 4

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

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

Класс может иметь только один прямой базовый класс.

Ответ 5

Основные отличия:

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

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

Ответ 6

Ссылка на Абстрактный класс против интерфейса.

Есть несколько сходств и различия между интерфейсом и абстрактный класс:

Класс может реализовывать несколько интерфейсы.
Класс может наследовать только один абстрактный класс.

Интерфейс не может предоставить какой-либо код, просто подпись.
Абстрактный класс может обеспечить полный, код по умолчанию и/или просто детали, которые необходимо переопределить.

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

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

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

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

Никакие поля не могут быть определены в интерфейсах
Абстрактный класс может иметь поля и константы определены

Ответ 7

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

Ответ 8

Интерфейсы позволяют определить структуру общего поведения.

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

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

Ответ 9

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

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