2014-11-26 2 views
0

Мне нравится концепция черт типа, потому что она решает некоторые вопросы дизайна прозрачным и расширяемым способом. Например, представьте, что у нас есть несколько классов принтеров и классов документов.Есть ли эквивалент типа символов из C++ на других языках?

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

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

// Documents 
class pdf { /* ... */ }; 
class txt { /* ... */ }; 

// Traits 
template<typename t> 
struct traits; // No default trait, so new documents throw compilation error 

template<> 
struct traits<pdf> { 
    static std::string get_title(pdf& document) { /* ... */ } 
    static std::string get_content(pdf& document) { /* ... */ } 
    static bool has_images = true; 
}; 

template<> 
struct traits<txt> { 
    static std::string get_title(txt& document) { return ""; } // Not supported 
    static std::string get_content(txt& document) { /* ... */ } 
    static bool has_images = false; 
}; 

// Printers 
class canon_printer : public printer { 
    template<typename T> 
    void print(T document) override 
    { 
     std::string title = traits<T>.get_title(document); 
     // ... 
     if (traits<T>.has_images) 
      // ... 
    } 
}; 

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

+1

В частности. Java или C#, Document and Printer будут интерфейсом или абстрактным классом, чтобы они могли меняться независимо друг от друга - это тот тип ответа, который вы ищете? – nos

+0

Я не знаю никаких языков, которые имеют что-то вроде шаблонов C++ со специализацией, но, опять же, кажется, что нужно было бы перечислить * все * языки, чтобы ответить на этот вопрос. –

+1

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

ответ

1

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

В вашем примере я не уверен, что вам нужны черты даже на C++. Ваша функция Printer::print, по-видимому, виртуальна (поскольку вы переопределяете ее в производном классе), но также является шаблоном; это не является законным в C++. Возможно, вам нужен какой-то вариант шаблона моста, используя виртуальные функции , даже в C++. Вы могли бы, например, есть абстрактный базовый класс вдоль линий:

class DocumentInformation 
{ 
public: 
    virtual ~DocumentInformation() = default; 
    virtual std::string get_title() const = 0; 
    virtual std::string get_content() const = 0; 
    // ... 
    virtual bool has_images() const = 0; 
}; 

Тогда для каждого типа документа, получить конкретный экземпляр:

class PDFDocumentInformation : public DocumentInformation 
{ 
    PDFDocument const& myDocument; 
public: 
    PDFDocumentInformation(PDFDocument const& document) 
     : myDocument(document) 
    { 
    } 
    std::string get_title() const override 
    { 
     // ... 
    } 
    // ... 
    bool has_images() const override { return true; } 
}; 

Вы (виртуальный) Printer::print затем принимает DocumentInformation const& и использует его для получения информации, необходимой ей .

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

+0

Спасибо, также за то, что показал мне ошибку в моем примере. – danijar

Смежные вопросы