GP与OO,欢迎讨论。
cber 2001-09-26 10:11:52 故事起源于左轻侯兄写的一篇《泛型编程在非C++语言中的实现之探讨》(http://www.csdn.net/develop/article/10/10694.shtm),在文章后面,我和另外几位大虾就此发表了各自的看法(我会把它们都列在下面的),结果也没有得到一个明确的结论。因此我把它们转贴过来,希望能够有高手参与讨论,好让我与大家都能够对此有一个清晰的认识。
看法是逆序存在的,因此可能会比较难看:(
jasonk ( 2001-9-25 15:34:13 )
从应用角度上,我觉得OO贴近系统构造,它一般都会支持一种对象模型,所以能够在运行状态下访问对象接口,并且有一定的继承层次.比如COM中的IDispatch,CORBA重的Object,Servant_Base.而GP更加贴近上层的程序员,它的彼此之间的联系比较松散,本质上也没有对象的概念.
cber ( 2001-9-25 11:58:28 )
我不同意lynxliu的说法,GP绝对不能说是OO的延伸。
之所以有Procedure-Based, Object-Based, Obeject-Oriented, Generic Programming等program paradigms,都是为了使软件开发更容易管理,使软件开发方式更好的符合人们的思维习惯。
平心而论,GP是一种相对来说很新的paradigm,所以还有很多人无法领悟其中的精髓(我也不敢说自己就已经领悟了),但要说它是OO的延伸,我是肯定不认同的。我比较赞同的观点是:COM/CORBA等面向组件的开发可以算是OO的延伸。
lynxliu ( 2001-9-25 10:18:08 )
文章里面所举的例子我感觉两类语言各有特色。GP是一次编程思想的革命,我觉得很奇怪。我认为,他只是OO思想的一个延伸。核心实际上是为了绕过强类型语言的数据类型检查!(这一点上VB做的更简单,因为没有类型声明与检查)。所以,谈不上什么更大的意义,只是在代码的集中控制和重用方面,有好处。(还不如不使用强类型语言)其他机制,在这两点上确实,比不上类模板实现。但是,类模板不是必须的,OO推荐的正式方式是使用工厂类,而不是静态的类继承,多态机制。我在写一本有关的书,里面对这个问题,是这么解释的,不知道大家怎么看。
cber ( 2001-9-25 9:24:50 )
Austern98这本书没有电子版,不过SGI上面的STL文档就是它的原始材料,应该可以说是等于它的70%多。你可以去上面找来看看,而且它还是免费的。
qinghou ( 2001-9-24 23:55:45 )
鼓掌鼓掌,精彩纷呈:-)
有几个朋友都同时指出,类型安全性是这种思路中的一个大问题
“这些Concept中很多requirement用operator overloading作会很方便,这应该算是C++的特色吧”
这话比较中肯:-)
这也等于说,从理论上来说,用函数实现requirement也没问题的
我现在的认识是,用这种思路实现GP,基本上是可以的,但是确实远不如C++方便
cber兄,《Generic Programming and STL》这本书有没有电子版可供下载?我没有见过比较好的讲GP的书
passos ( 2001-9-24 21:57:06 )
我们也知道GP对于代码复用来说是非常有用的。
那么我们可以撇开C++的GP实现不说,是否有可能利用Delphi自身的条件来
实现GP所能够达到的效果呢?
毕竟我们不是要用Delpi重新写一遍C++的STL啊。
我想关注一下实际的效果应该还是有实际意义的。
cber ( 2001-9-24 17:03:43 )
GP是一种新的programming paradigm,和OOP基本上不搭界。根据Matt Austern在《Generic Programming and STL》中的见解,GP最核心的应该是Generic,表现为一堆的Concept组成的Hierarchy,其地位对应于OO中的Class Hierarchy。因此,要想彻底掌握GP,最好能够先将OOP抛一边,转而理解它独有的Concept Hierarchy中的精髓,然后再试图去理解这些Concept的实现。
STL中的algorithms中并没有强制要求要有operator overloading,它只是对每个algorithm有着一些Concept上面的要求,只要实作中参与该algorithm的元素(如sequence,element,iterator等)能够符合这些Concept的话,就认为该算法的实作品是一个合格的实作,而这些Concept中很多requirement用operator overloading作会很方便,这应该算是C++的特色吧^_^
我说单根继承的Serialization是强项,因为是它比较容易实现。而如C++式的继承方式,你将不得不对每个继承体系都来一次Serialization的实作,这是很烦人的(虽然它确实很符合我们的思维习惯)。
个人认为,要想学习好GP,可以看一部分有关哲学方面的书籍,可能会更好点。例如,我对于GP和OO的理解就是:OO体现了世界是由物体组成的;而GP则体现了世界是运动着的世界,我们应该透过各种不同的运动的表面去抓住它们的本质(也就是Generic)^_^
smartkid ( 2001-9-24 15:29:00 )
再说两句:
1)GP从其本质来说是算法与数据的分离,在面向对象语言中,它一般通过将一系列抽象的算法类来完成,并同时定义了算法类所处理的数据类。从这个角度上来说,它并不一定要利用模板才能实现。
2)模板的本身是对类的处理,而不是对对象的处理。所以模板为GP的实现提供了最佳的支持。
3)单根继承的Serialization比较容易实现,多重继承的Serialization更体现了面向对象的本意。这个话题其实说深了就是多重继承是否合适的问题,不仅限于Serialization。多重继承我认为要比单根继承更加合理,只是由于多重继承往往不容易被使用者掌握,所以很多面向对象语言都采用了单根继承。
4)Delphi的RTTI功能是不错,但RTTI和GP完全是两回事,不存在谁能替代谁的问题。
5)运算符重载和GP也是两回事。GP可以重载运算符来实现,也完全可以通过函数重载来实现。其实运算符重载并不能实现比函数重载更多的功能,它的作用只是让程序看起来显得“似乎”简单些。
6)Delphi完全可以实现GP,只是它的实现不如C++的实现好用:-)。要完整地实现GP,我觉得有至少要能够实现模板,对于多重继承勉强可以通过接口或对象组合来部分地模拟。
smartkid ( 2001-9-24 15:01:27 )
左兄鉴:
C++模板有两个在Delphi/Java体系结构中无法实现的优势:
1)避免了运行时动态类型转换的开销
2)编译阶段的类型检查
在Delphi/Java的实现中,如果想实现静态的成员类型检测必须通过从TStack继承或组合TStack来完成。
对Delphi有一个比较好的STL的实现,是个开放源码的项目: http://sourceforge.net/projects/decal/
smartkid@nari-china.com
qinghou ( 2001-9-24 13:23:58 )
说明一下:
我对很多东西的理解都没有把握,写下本文的目的完全是抛砖引玉,希望能够看到精彩的回复,增长自己的水平。发在几个坛子之后,回复比较踊跃,但是显然大家也分歧很大,众说纷坛,有的完全相反。而各位高手的发言又往往是点到为止,没有深入,让我这样的人看了更增疑惑。比如,有人认为模板是GP的必要条件,有人却认为模板跟GP毫无关系;cber认为serialize是单根结构的强项,但在大富翁上有人却认为C++中通过多重继承来实现serialize要远为灵活轻便……
能否请发言的高手多花一些时间,来充分阐明自己的观点?例如wao兄,你说的“非常强大的动态类型”是指什么?为什么有了它就不需要GP了呢?cber兄,你认为algorithm的实现必须使用运算符重载吗?如果Delphi/Java中增加运算符重载,是否就可以完整地实现GP呢?……
如果这个贴子能引起一场讨论,则我辈幸甚。
最后重复一句:“我的目的也不是一定要让Delphi/Java来跑GP,而是想探讨一下GP这种思想以另外一种思路实现的可能性。”我们当然不可能改变Delphi/java的语法,但可以讨论一下应该怎样改变语法,才能以另一种思路实现GP。这种纯理论的探讨也是很有意思的啊。
qinghou ( 2001-9-24 12:13:56 )
谢谢,我去找找DeCAL看
各位能推荐一些关于GP的专门书籍么?一般的C++资料说得都不详细
wao ( 2001-9-24 9:09:23 )
Java/Ojbect Pascal 是不需要GP的。因为他们有非常强大动态类型,并且效率根本就不是这种语言的出发点。例如smalltalk压根就没有静态类型,全部是运行时再确认的。
kundeng ( 2001-9-24 9:01:24 )
左大侠对号称Delphi STL的DeCAL库有什么看法?
我在SOurceforge上看到了这个库,早早下载了,但是却没有时间看,希望左大侠给我们吹一吹。
如果您没有DeCAL库,可以在http://sourceforge.net用关键字“Delphi STL”搜索到。
cber ( 2001-9-24 1:25:21 )
看完你的做法,感觉和MFC中的Collection Classes差不多。我认为,把所有的类都继承自同一个base是一个很蹩脚的做法:)还有,你在这篇文章中还没有讲如何实作GP中的另一个重要组成部分:algorithm,而在实作slgorithm时恰恰大量使用了操作符重载,这不能不说是现今的Delphi/Java的遗憾了。不过C++中现有的STL也不是很完美,至少它还不能实现serialize,这恰好是同一祖先的强项:(
我也比较赞同myan的说法:“每种语言都有最擅长的特点,不必非要以己之短,搏彼之长”。要知道,强扭的瓜通常都是不甜的,要真的想在Delphi/Java中实现完全的GP,还是等到它们支持足够多的必需语法再说吧。
bonly ( 2001-9-23 22:20:00 )
始终还是C++的优秀!!!
cber ( 2001-9-23 22:13:32 )
先做个标记,回头好好看看再说。
qinghou ( 2001-9-23 13:06:59 )
可能是我对GP的了解不对吧
我的印象中,GP主要就是将数据类型和通用算法独立起来的一种思想,从而可以在更高的层次上实现代码复用
至于实现是静态还是动态,似乎不是GP的特性吧?
能否说一说您对GP的理解?
我的目的也不是一定要让Delphi/Java来跑GP,而是想探讨一下GP这种思想以另外一种思路实现的可能性。这样可以加深我们对GP、对C++、对Delphi/Java的理解。
babysloth ( 2001-9-22 23:26:41 )
感觉左大侠的说法不对。
C++的GP是静态的,GP的效率与抽象并重。
您所说的是动态的,不算GP。
Java在OO上出色,GP却不行,何必强求老虎爬树呢?
qinghou ( 2001-9-22 19:46:15 )
我明白你的意思
Delphi/Java中对GP的实现,与C++对GP的实现是完全不同的两种思路,因此在template编程这个层次,根本不具有可比性,也不存在谁跑在前面的问题。但我关注的不是这个,而是GP本身。GP的思想本身,应该与语言是无关的。所以我也不同意“以己之短,搏彼之长”的说法。
“Object Pascal/Java/C#在面向对象和面向组件领域,较之C++有着明显的优势”,你指的是哪一方面?
myan ( 2001-9-22 18:53:28 )
你所使用的这种GP实现技术,基本上就是Smalltalk/Java中已经应用的泛型技术。当然不能说不是GP,但是跟C++的GP实在太不相同了。后者实际上是一种静态多态性技术,基于编译时的运算,大量运用template技术,以至于形成了所谓template metaprogramming风格。这方面,现在只有C++语言远远地跑在前面,包括Java打算引入的泛型机制,也远远没有达到今天C++的层次。
每种语言都有最擅长的特点,不必非要以己之短,搏彼之长。Object Pascal/Java/C#在面向对象和面向组件领域,较之C++有着明显的优势,好好地发挥这种长处吧!