【问题标题】:Why some C API doesn't follow Encapsulation为什么某些 C API 不遵循封装
【发布时间】:2018-07-27 19:00:48
【问题描述】:

例如,如果我需要获取目录中的文件,

封装:

struct dirent *ent;
ent = readdir (dir);
char *filename = d_name(ent);

C:

struct dirent *ent;
ent = readdir (dir);
char *filename = ent->d_name;

【问题讨论】:

  • 没有理由你不能拥有一个返回文件名的函数d_name
  • 结构字段可以直接访问,所以人们会这样做。但是您可以创建一个宏(使用其他名称)或一个函数来执行该封装。
  • 另外,ent 数据可能是内部状态的副本,所以它已经封装在一个结构中
  • 为什么早于 OOP 概念的 C API 会遵循其原则?
  • 使用 getter 而不是直接访问字段并不会自动暗示封装。

标签: c oop


【解决方案1】:

考虑以下两种 API 变体:

struct point get_location(const foo *f)
{
    struct point p;
    p.x = f->something_x;
    p.y = f->something_y;
    return p;
}

对比:

double get_location_x(const foo *f)
{
    return f->something_x;
}
double get_location_y(const foo *f)
{
    return f->something_y;
}

我声称没有什么比前者更“封装”后者了。您是否将前者的结果类型视为值类型只是一个角度问题。同样,struct dirent 是一个值类型,其定义明确且稳定/固定。正如@Jean-FrançoisFabre51 所评论的,它是从封装在DIR 对象中的某些内部状态获得的结果值。

【讨论】:

  • 如果我们使用不透明的指针,它会变得更加封装a la FILE.
  • @EugeneSh.: DIR 类似于 FILEstruct dirent 类似于您从带有fread 的文件中读取的数据。
  • 在我看来,您的示例中的“struct dirent”和“struct point”都是类类型,而不是原始类型/值类型。尽管它很简单且规范明确。你能证明你的观点吗?
  • 我能想到的一个理由是struct dirent 是不可变的,这使得方法变得不必要。不过,我不知道如何为struct point 辩护。
  • 在一个给定的平台上,struct dirent 是稳定的,但是 POSIX 只定义了两个成员——d_inod_name——但是一些实现提供了额外的字段(d_namlen,也许是d_type,也许其他人)。
猜你喜欢
  • 1970-01-01
  • 2015-01-09
  • 2017-09-23
  • 1970-01-01
  • 2014-12-09
  • 2016-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多