在寒假那次作业中渐渐意识到应该把面向对象作为一种思想来使用,而不要受所使用的语言限制。而产生这样的想法也是因为在 C 中要使用面向对象的思想必须要自己来使用一些技巧。
比如对 C 里面定义的某个 struct 类型,当定义操作这个类型的函数时,让函数都接受这个 struct 类型的指针为参数,函数作用在指针所指向的对象上。在 C++ 中形如 object.function() 的函数调用在背地里就传了指向 object 对象的指针给 function,当然在类中定义这个方法的时候你可以看到这个指针,也就是 this 了。
而在 C 里面要使用继承的思想的话也不是不可以。对于父类的成员要在子类里面也能够访问的话直接在子类的 struct 里面包含一个父类的 stuct 就可以了,当然这样做的话要访问父类的成员会需要写成 descendants->parent->somemember 而不能直接写 descendants->somemember,而且访问控制也没有办法由编译器来控制。
对于多态通过函数指针也是可以实现的(Rob Pike 在 Notes On Programming in C 中说到 “I argue that clear use of function pointers is the heart of objectoriented programming.”)。这时要把函数指针作为类的成员,父类和子类需要手工设置不同的函数指针。对函数指针在 struct 定义中出现的位置可能也会有限制,目前我还没有做太多的考虑,也没有试过。关于使用 C 来进行面向对象编程有人写了一本书 Object-Oriented Programming wich ANSI C,有时间的话打算看看了。
当然,直接使用 C 来做面向对象的编程肯定会有许多不便,要不然也不需要所谓的面向对象语言的出现。但是面向对象的语言只是从语言层面上让我们更容易地表达面向对象的思想。语言本身不是核心,语言是我们表达思想的媒介,思想才是核心。当然好的语言能让我们更好、更方便地思考和表达思想,所以在进行面向对象编程的时候选择一种面向对象的语言还是有必要的。
关于使用语言来表达面向对象思想的问题还可以看看 Common Lisp 作为函数式语言是如何做到的。Common Lisp 在面向对象成为主流之前就已经出现,它实现面向对象的机制不是通过像 C++,Java 采用的 message passing,而是通过将函数特化于对象的方式。虽然我还没有在实际的程序中使用过 Common Lisp,但是感觉 Common Lisp 的对象机制比 C++,Java 灵活许多(不知道实际使用会不会更复杂),而且也有 AOP 的影子在其中。更令人惊叹的是这个对象机制的实现使用了大量的 macro(我不知道是不是只是使用了 macro),从使用 macro 来是语言具有面向对象的能力也可以证明面向对象只是思想,而不是语言本身。
最后一点是虽然面向对象的思想很好,但是它也不是万能的。有些程序不用面向对象的思想反而能得到更简单的解决办法。总觉得在用设计模式的时候很容易把设计搞的很大,可能还是我能力不够的原因吧。