Stay Hungry.Stay Foolish.
c语言面向对象接口设计之痛

先上代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct _stu Stu;

struct _stu {
    int id;
    int age;
};

Stu * 
init(int id, int age)
{
    Stu *stu = (Stu*)malloc(sizeof(Stu));
    stu->id = id;
    stu->age = age;
    return stu;
}

char *
get_info(Stu *stu)
{
    char    buf[1024];

    sprintf(buf, "id是[%d], 年龄是[%d]", stu->id, stu->age);
    return strdup(buf);
}

void
destory(Stu *c)
{
    free(c);
}

int main()
{
    int     id = 1;
    int     age = 23;

    Stu *stu = init(id, age);
    char *info = get_info(stu);
    printf("%s\n", info);
    free(info);
    return 0;
}

事情是这样的,想撸一把Golang,然后看到了云风大牛的一篇文章<<Go 语言初步>> 原话是这样的

mix-in 的接口风格。非常接近于我在用 C 时惯用的面向对象风格。有语法上的支持要舒服多了。以平坦的方式编写函数,没有层次。而后用 interface 把需要的功能聚合在一起。没有继承层次,只有组合功能。

然后看了下<用 C 时惯用的面向对象风格>这篇文章。

面向对象编程不是银弹。大部分场合,我对面向对象的使用非常谨慎,能不用则不用。相关的讨论就不展开了。

但是,某些场合下,采用面向对象的确是比较好的方案。比如 UI 框架,又比如 3d 渲染引擎中的场景管理。C 语言对面向对象编程并没有原生支持,但没有原生支持并不等于不适合用 C 写面向对象程序。反而,我们对具体实现方式有更多的选择。

大部分用 C 写面向对象程序的程序员受 C++ 影响颇深。企图用宏模拟出一个常见 C++ 编译器已经实现的对象模型。于我愚见,这并不是一个好的方向。C++ 的对象模型,本质上是为了追求实现层的性能,并直接体现出来。就有如在 C++ 中被滥用的 inline ,的确有效,却破坏了分离原则。C++ 的继承是过紧的耦合。

我所理解的面向对象,是让不同的数据元有共同的操作方式,适合成组的处理。根据操作方式的不同,我们会对数据元做不同的分组。一个数据可能出现在这个组里,也可以出现在那个组里。这取决于你从不同的方面提取的共性。这些可供统一操作的共性称之为接口(Interface),接口在 C 语言中,表现为一组函数指针的集合。放在 C++ 中,即为虚表。

我所偏爱的面向对象实现方式(使用 C 语言)是这样的:

若有一组数据,我们需要让他们看起来都有一种叫作 foo 的共性。把符合这样的数据都称为 foo_object 。通常,我们会有如下 api 去操控 foo_object 。

struct foo_object; struct foo_object * foo_create(); void foo_release(struct foo_object *); void foo_dosomething(struct foo_object *);
在具体实现时,会在一个叫 foo.c 的实现文件中,定义出 foo_object 结构,里面有一些 foo_dosomething 所需的数据成员。

感触颇深,代码就是数据结构加算法,foo_object就是数据结构,算法就是foo_dosomething的实现,如此而已:)

最后,我觉得云风看好Go的原因之一就是Go这么写

package main

import (
    "fmt"
    "math"
)

type Vertex struct {
    X float64
    Y float64
}

func (v Vertex) Abs() float64 {
    return math.Sqrt(v.X * v.X + v.Y * v.Y)
}

func main() {
    vertex := Vertex{1,2}
    fmt.Println(vertex.Abs())
}

这段的Go代码想要表达的和C是一样的,操作Vertex这个数据结构实现一些算法(Abs方法)。个人感觉是真正掌握了面向对象思想的C专家,然后又深恶痛绝C的笨拙写法制造出的Go现在这种写法。

附上一段洗脑的话: 我发现我花了四年时间锤炼自己用 C 语言构建系统的能力,试图找到一个规范,可以更好的编写软件。结果发现只是对 Go 的模仿。缺乏语言层面的支持,只能是一个拙劣的模仿—by云风

自由转载-非商用-非衍生-保持署名(创意共享3.0许可证
评论

暂无评论~~