Интерфейсы - какой смысл? - PullRequest
241 голосов
/ 23 июля 2011

Причина интерфейсов действительно ускользает от меня.Насколько я понимаю, это своего рода обходной путь для несуществующего мульти-наследования, которого нет в C # (или мне так сказали).

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

простой пример (взят из другого вклада переполнения стека)

public interface IPizza
{
    public void Order();
}

public class PepperoniPizza : IPizza
{
    public void Order()
    {
        //Order Pepperoni pizza
    }
}

public class HawaiiPizza : IPizza
{
    public void Order()
    {
        //Order HawaiiPizza
    }
}

Ответы [ 28 ]

6 голосов
/ 23 июля 2011

Учтите, что вы не можете использовать множественное наследование в C #, а затем снова посмотрите на свой вопрос.

5 голосов
/ 23 июля 2011

Интерфейс = контракт, используется для слабой связи (см. GRASP ).

4 голосов
/ 23 июля 2011

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

Итак, вы вызываете фабричный метод: MyInterface i = MyGraphics.getInstance(). Затем у вас есть контракт, и вы знаете, какие функции вы можете ожидать в MyInterface. Таким образом, вы можете вызвать i.drawRectangle или i.drawCube и знать, что если вы меняете одну библиотеку на другую, функции поддерживаются.

Это становится более важным, если вы используете Dependency Injection, так как в XML-файле вы можете заменить реализации.

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

Это широко используется в коллекциях в .NET, так как вы должны просто использовать, например, List переменные, и не волнуйтесь, был ли это ArrayList или LinkedList.

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

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

4 голосов
/ 23 июля 2011

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

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

public void Order();

После вашего упомянутого кода вы можете получить что-то вроде этого:

public void orderMyPizza(IPizza myPizza) {
//This will always work, because everyone MUST implement order
      myPizza.order();
}

Таким образом, вы используете полиморфизм, и все, что вас волнует, это то, что ваши объекты реагируют на order ().

3 голосов
/ 26 января 2016

Я выполнил поиск по слову «композиция» на этой странице и ни разу не увидел его. Этот ответ во многом дополняет вышеупомянутые ответы.

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

Это превосходное учебное пособие «Шаблон декоратора» Дерека Банаса (который - как ни странно - в качестве примера также используется пицца) является достойной иллюстрацией:

https://www.youtube.com/watch?v=j40kRwSm4VE

2 голосов
/ 23 июля 2011

Интерфейс определяет договор между поставщиком определенной функциональности и соответствующими потребителями. Он отделяет реализацию от контракта (интерфейса). Вы должны взглянуть на объектно-ориентированную архитектуру и дизайн. Вы можете начать с Википедии: http://en.wikipedia.org/wiki/Interface_(computing)

2 голосов
/ 21 марта 2013

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

Давайте расширим аналогию с пиццей, чтобы сказать полноценное блюдо из 3 блюд.У нас по-прежнему будет базовый интерфейс Prepare() для всех наших категорий продуктов питания, но у нас также будут абстрактные объявления для выбора блюд (закуска, основное блюдо, десерт) и различные свойства для типов продуктов (пикантная / сладкая, вегетарианская / не-вегетарианское, без глютена и т. д.).

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

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

2 голосов
/ 26 июля 2011

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

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

2 голосов
/ 23 июля 2011

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

public class Car { ... }

public class Tree { ... }

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

public class Car : IBurnable
{
public void Burn() { ... }
}

public class Tree : IBurnable
{
public void Burn() { ... }
}
2 голосов
/ 29 августа 2014

Вот интерфейс для объектов, имеющих прямоугольную форму:

interface IRectangular
{
    Int32 Width();
    Int32 Height();
}

Все, что требуется, - это реализовать способы доступа к ширине и высоте объекта.

Теперь давайте определим метод, который будет работать с любым объектом IRectangular:

static class Utils
{
    public static Int32 Area(IRectangular rect)
    {
        return rect.Width() * rect.Height();
    }
}

Возвращает площадь любого прямоугольного объекта.

Давайте реализуем класс SwimmingPool, который является прямоугольным:

class SwimmingPool : IRectangular
{
    int width;
    int height;

    public SwimmingPool(int w, int h)
    { width = w; height = h; }

    public int Width() { return width; }
    public int Height() { return height; }
}

И еще один класс House, который также прямоугольный:

class House : IRectangular
{
    int width;
    int height;

    public House(int w, int h)
    { width = w; height = h; }

    public int Width() { return width; }
    public int Height() { return height; }
}

Учитывая это, вы можете вызвать метод Area в домах или бассейнах:

var house = new House(2, 3);

var pool = new SwimmingPool(3, 4);

Console.WriteLine(Utils.Area(house));
Console.WriteLine(Utils.Area(pool));

Таким образом, ваши классы могут «наследовать» поведение (static-методы) от любого количества интерфейсов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...