在其他语言中是否有类似于C ++的类型特征?

时间:2014-11-26 11:09:23

标签: c++ typetraits

我喜欢类型特征的概念,因为它以清晰和可扩展的方式解决了一些设计问题。例如,假设我们有几个打印机类和文档类。

由于以后可能会添加新的文档类型,因此打印机不应该直接知道它正在打印哪个文档,因此不必对其进行调整。另一方面,文档不应该知道所有打印机。

通过提供有关如何打印文档的特征,这是添加新文档时唯一必须修改的地方。此外,如果有新的打印机,它们可以直接使用相同的特性,并专注于与其他打印机不同的内部打印过程。

// 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 个答案:

答案 0 :(得分:1)

这取决于你使用的特性。对于许多用途,一些 战略模式的形式将是一个适当的解决方案。你&#39; 11 得到运行时分辨率,而不是编译时间,你不能真的 但是,用它来定义类型。

在您的示例中,即使在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。事实上,这就是 通常情况;只有拥有现有文档时才需要桥 具有不兼容接口的类。