C中没有任何语法技巧可以实现方法链接正如在其他一些语言中可能使用的那样。在 C 中,您可以编写单独的函数调用,将对象指针传递给每个函数:
Widget *w = getWidget();
widgetSetWidth(w, 640);
widgetSetHeight(w, 480);
widgetSetTitle(w, "Sample widget");
widgetSetPosition(w, 0, 0);
对于 C++ 和其他 OOP 语言中的方法调用也可以完成同样的操作:
Widget *w = getWidget();
w->SetWidth(640);
w->SetHeight(480);
w->SetTitle("Sample widget");
w->SetPosition(0, 0);
使用上述 API,并假设每个方法返回this
对象,方法链接语法如下所示:
getWidget()->SetWidth(640)->SetHeight(480)->SetTitle("Sample widget")->SetPosition(0, 0);
这是否比单独的语句更具可读性取决于品味和本地编码约定。我个人觉得它很麻烦,更难读。在代码生成方面有一个小优点:下次调用时不需要从局部变量重新加载对象指针。这种微小的优化很难证明链接语法是合理的。
一些程序员尝试通过这种方式让它变得更容易接受:
getWidget()
-> SetWidth(640)
-> SetHeight(480)
-> SetTitle("Sample widget")
-> SetPosition(0, 0);
再说一次,这是一个品味和编码约定的问题……但是 C 语言的等价物看起来确实很尴尬:
Widget *w = widgetSetPosition(widgetSetTitle(widgetSetHeight(widgetSetWidth(getWidget(), 640), 480), "Sample widget"), 0, 0);
并且没有简单的方法可以将这个链重新组织成更具可读性。
请注意,一些最古老的 C 库函数可以链接到:
const char *hello = "Hello";
const char *world = "World";
char buf[200];
strcpy(buf, hello);
strcat(buf, " ");
strcat(buf, world);
strcat(buf, "\n");
可以重组为:
strcat(strcat(strcat(strcpy(buf, hello), " "), world), "\n");
但更安全且更受青睐的方法是:
snprintf(buf, sizeof buf, "%s %s\n", hello, world);
欲了解更多信息,您可能想阅读以下内容:
Marco Pivetta (Ocramius):流畅的界面是邪恶的
另请注意,如果 C 对象具有用于这些调用的函数指针成员,则可以使用上述所有语法,但仍必须将对象指针作为参数传递。函数指针通常分组在对象中存储指针的结构中,模仿 C++ 虚拟方法的实现,使语法稍微重一些:
Widget *w = getWidget();
w->m->SetWidth(w, 640);
w->m->SetHeight(w, 480);
w->m->SetTitle(w, "Sample widget");
w->m->SetPosition(w, 0, 0);
将它们链接起来也是可能的,但没有真正的好处。
最后,应该注意的是,方法链接不允许显式的错误传播。在 OOP 语言中,链接是惯用的,可以抛出异常以或多或少令人满意的方式发出错误信号。在 C 中,处理错误的惯用方法是返回错误状态,这与返回指向对象的指针相冲突。
因此,除非保证方法成功,否则建议不要使用方法链并执行迭代测试:
Widget *w = getWidget();
if (SetWidth(w, 640)
|| SetHeight(w, 480)
|| SetTitle(w, "Sample widget")
|| SetPosition(w, 0, 0)) {
/* there was an error, handle it gracefully */
}