Что лучше передать функции в качестве параметра *интерфейс * или * объект*?

StackOverflow https://stackoverflow.com/questions/1003009

Вопрос

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

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

Согласны ли вы, что разделение большого класса на интерфейс (ы) является хорошей практикой?
Есть ли какие-либо недостатки в этом?

Пример:

public interface class IVeryLargeClass
{
    void DoSomething();
    ...
};

public ref class VeryLargeClass : public IVeryLargeClass
{
public:
    virtual void DoSomething() { ... }
    ...
};

public ref class AnotherClass
{
public:
    AnotherClass(VeryLargeClass^ vlc)  { vlc->DoSomething(); }
 // OR
    AnotherClass(IVeryLargeClass^ vlc) { vlc->DoSomething(); }
};
Это было полезно?

Решение

Один из первых принципов, который вы изучаете при разработке OO:

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

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

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

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

Другие советы

В Принцип инверсии зависимостей можно суммировать как:Лучше зависеть от абстракций, чем от конкретизации.

Почти всегда лучше передать интерфейс, чем передать конкретный класс.

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

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

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

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

http://en.wikipedia.org/wiki/Interface_ (computer_science) (компьютерная наука)

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top