我喜欢类型特征的概念,因为它以清晰和可扩展的方式解决了一些设计问题。例如,假设我们有几个打印机类和文档类。
由于以后可能会添加新的文档类型,因此打印机不应该直接知道它正在打印哪个文档,因此不必对其进行调整。另一方面,文档不应该知道所有打印机。
通过提供有关如何打印文档的特征,这是添加新文档时唯一必须修改的地方。此外,如果有新的打印机,它们可以直接使用相同的特性,并专注于与其他打印机不同的内部打印过程。
// 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 ++中看到过这个概念。其他编程语言中是否有类似的概念?我更多地寻找这种方法的语言独立术语而不是语言列表。
答案 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
。事实上,这就是
通常情况;只有拥有现有文档时才需要桥
具有不兼容接口的类。