先上代码
#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云风
评论
暂无评论~~