2014-12-25 2 views
2

В Effective Objective-C, Matt Galloway предлагает следующее:..Должны ли вы переслать объявление как можно больше?

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

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

ответ

2

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

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

Вот краткий пример: допустим, вы хотите использовать класс SingleWidget в своем классе DoubleWidget. Однако интерфейс, который предоставляет ваш класс, всегда использует SingleWidget через указатель или через ссылку; только реализация вызывает методы SingleWidget. Предложение Мэтта это сделать это

DoubleWidget.h

// Use forward declaration in the header 
class SingleWidget; 

class DoubleWidget { 
    SingleWidget &one; 
    SingleWidget &two; 
public: 
    DoubleWidget(SingleWidget& a, SingleWidget& b) : one(a), two(b) {} 
    void play(); 
}; 

DoubleWidget.cpp

#include "SingleWidget.h" 
// Include the header when you cannot avoid including it 
#include "DoubleWidget.h" 

void DoubleWidget::play() { 
    one.play(); 
    two.play(); 
} 

вместо этого:

DoubleWidget.h

// Do not include the header where a forward declaration is sufficient 
#include "SingleWidget.h" 

class DoubleWidget { 
    SingleWidget &one; 
    SingleWidget &two; 
public: 
    DoubleWidget(SingleWidget& a, SingleWidget& b) : one(a), two(b) {} 
    void play(); 
}; 

DoubleWid get.cpp

#include "DoubleWidget.h" 

void DoubleWidget::play() { 
    one.play(); 
    two.play(); 
} 

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

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

У вас есть какая-то связь там, но она очень слабая: ваш класс знает, что существует другой класс, и это все. Напротив, когда вы включаете заголовок, ваш класс знает все о другом классе: он знает его структуру, функции-члены, классы, на которые полагается другой класс, и т. Д. Это хорошая идея не «сбрасывать» всю эту информацию в открытый интерфейс вашего собственного класса.

+0

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

+0

Спасибо за эту заметку. Скажете ли вы тогда * только *, если он предназначен исключительно для среднего человека, что его следует переслать? Если нет, заголовок должен быть объявлен? Проблема, которую я вижу при использовании форвардной декларации на протяжении всего проекта, - это цепная реакция, которую она может вызвать - это означает, что клиенту потенциально придется импортировать несколько заголовков только для использования одной вещи, потому что все, включая свойство свойства и т. Д., Использует форвардную декларацию. – Boon

+0

Я пытаюсь избежать сюрпризов esp в случае, когда я возвращаю объект типа из моего метода. Клиент не сможет использовать его вообще, не импортируя его. Я все еще не получаю коэффициент зависимости, потому что в силу использования прямого объявления зависимость уже установлена. Это не то, что мы используем id. – Boon