泛型编程在Delphi中的实现(200分)

  • 主题发起人 左轻侯
  • 开始时间
Y

yysun

Unregistered / Unconfirmed
GUEST, unregistred user!
选择,下面哪些是属于“泛型”Generic Programming ?

A. VB 中的 Collection
B. Delphi 中的 TList
C. Java 中的 Vector
D. C++ STL 中的 list

在讨论“泛型编程在Delphi中的实现”以前,先弄清楚实现什么吧。[?]
 
D

dream_soft

Unregistered / Unconfirmed
GUEST, unregistred user!
我所认为的GP,正如在上文中所说,"是类型安全的类型无关性,是将数据类型当
成数据进行处理的一种理念",使代码达到类型无关而达到的通用性。它概不等于Concept
也不等Concept + tempalte。实际上类引用就很好的表现出了GP的思想,而Factory Method
也是对这种思想的对象创建部分一种很好的解答。
我并不认为没有Template不算GP,因为GP是一种类型无关的思想。就像在过程程序语言
中也可以使用OO的思想一样。但编译器的直接支持使思想变为实现更为方便,在这种意义上,
我要说,没有C++的Templatet或Ada中generics这样的支持,不能算是一种GP语言。
 
M

mikedeakins

Unregistered / Unconfirmed
GUEST, unregistred user!
真没办法,C++ 把语言的语义高度完善,所以 C++ 可以实现很多其他语言必须以扩充
关键字才能实现的功能(操作符模糊、类型无关等等)。
Pascal 则是一个简单的面向对象语言(不支持操作符重载、模板、多重继承),不具备
几个“看起来并不重要的”特性。我觉得没必要苛求 Pascal 实现 C++ 的泛型功能,
Pascal 工程必须精心构造一个庞大的类树,这就不可避免地降低了可维护性。RTTI 的
使用也完全不是替代模板的良方,一方面,RTTI 在使用当中必然导致性能下降和冗余
代码的出现。另一方面,大家仔细想想,RTTI 真的能够替代模板?说这种话的人不是
白痴就是别有用心。
 
D

dream_soft

Unregistered / Unconfirmed
GUEST, unregistred user!
To yysun:
对了,我也有和flier同样的看法:能不能请你不要说"您"啊?朋友间这样称呼听上去挺
别扭的,不是吗?
[:D][:D][:D]
 
F

flier

Unregistered / Unconfirmed
GUEST, unregistred user!
争论到现在,我觉得已经有点偏离主体了,而且大家开始纠缠不清了,呵呵
我看应该按yysun的思路,将目前的几个核心问题揪出来,然后有针对性地进行讨论

首先,是gp到底是什么的问题。
我和yysun的观点的最大差别就是,template对于是gp来说到底处于什么
地位。我以为他是工具而不是目的,很有用但不是必须。C++和Delphi/java
一类语言有很大不同。前者为兼容C保留了很多东东,而且功能强大,灵活性大,
因此进化出了template这个工具,而且因为template的进化和GP的发展
可以说是相辅相成的,因此现有的很多资料包括yysun将两者混为一谈,认为离开了
template就没有gp。但是就像我前面分析的,gp实际上只是一种从更高层次上
进行抽象的方法论而已,这种思想体系映射到不同语言有不同实现方式。在C++
里面,通过template实现concept及类型无关;而在delphi/java里面以接口
及单根类树来实现。gp的核心思想是静态的算法与动态的操作元素分离,至于如何
分离只是体现这种思想的方式,而template恰恰处在这个地位,因此我说template
是实现gp的工具。当然因为我前面提到的原因,template对gp可以非常出色的贯彻
执行,有了template可以给使用者带来很大的便利。但并不能因为没有template
就称之不是gp。
举个不是很恰当的例子。在汇编语言里,本来是可以是没有循环语句的,可以通过
一系列的整数运算和条件判断语句,实现循环这个概念。(实际上以前在386下为了
优化程序效率,很多情况下用这种方式替代速度较慢的LOOP。而且在CPU的微指令一级,
循环肯定也是这样实现的)这时一种新的语言出现了,比如说PASCAL他提出了循环
这个概念的新实现,并且通过FOR,WHILE,DO等等关键字实现了他。新的语言中有效率
非常高、而且结构清晰、自动类型检测等等编译器级特性支持的循环实现,如果用惯了
这种新语言的人,可能就认为循环就是FOR,FOR就是循环。而实际上循环是一个思想,
他映射到汇编中是一系列整数操作和判断指令,映射到PASCAL里是FOR等编译器
内建支持语句,你能因为汇编没有FOR就说汇编里那些语句不是循环吗?就算是汇编
有LOOP,我用DEC ECX, JNZ Loop_Begin实现的难道不是循环吗?GP和template
的关系也类似于此,一个是思想,一个是技术,更本不是一个层面上的东西,你怎么
能把它绑到一起呢?
当然,这个例子运用在这里有他不妥之处,我只是借他说明一个道理而已。

其次,是类型安全
这里的主要分歧,大概就是一个检测时间、一个效率,两个问题。(检测时间指的是
类型判定是何时进行?编译时或运行时,template实现方式是前者,单根类树RTTI
检测是后者。)我觉得完全没有必要为孰优孰劣做争论。因为这在不同的应用范围中
有不同的需求。比如一个工作在内核中的网卡转包程序,对时间考虑的精度已经达到
ns级,你要他用RTTI肯定要有人发疯的 :) 但是如果你对一个财务软件,数据库操作
本来就慢的要死,谁还在乎进行检测这十几个CPU周期?我的观点是,除非那些真正的
核心代码段,比如进行图象处理,网络程序的核心函数等等,其他大部分情况应该以程序的
简洁、易懂、或者说可维护性、可扩展性为主。毕竟大部分函数在你程序运行时,一共
也才执行几次,那种频繁执行的函数少之又少。何况这种非算法的优化实在是效果有限
不如等一年半你产品开发出来时买快一倍的CPU来得快,呵呵
你可以找个Turbo Profile之类的工具将你编写的各种程序测试一下,看看真正
经常调用的函数是那些,比例多大,复杂性多大。
但是,类型检测必须要有,而且范围越窄越好,因为人的因素是不确定的,必须以
技术约束来降低因为人的因素带来的潜在风险,这也是为什么我最喜欢C++语言,但是
平时做项目写程序多用Delphi的原因(因为C++太强大、太灵活,反之Pascal非常严谨)

最后,是GP与OO的关系
我前面文章里大概谈过我的一些看法,一个大概的发展路线是OO->IO(CO)->GP
(IO/CO指Interface-Oriented或者Component-Oriented,两者有区别但是联系很紧密)
但GP不仅仅是IO的发展,他还从Procedural Model和Object-Based Model
吸取了很多思想。前面dream_soft说看我把GP说得像Procedural Model,
其实两者本来就有很多相似之处,只是抽象的层次不同,应用的对象不同而已;
而GP在实现中更多地是以OB的形式而不是OO的形式,你看STL实现中virtual几乎没有
这也是GP与重要冲突OO的区别之一。因此GP不是简单的对某种现有model的发展或取代
他更多的是起到一种补充的作用,也就是说OO+GP+???来实现程序的构建。前面yysun
说GP有时并不比OO强,正确,因为GP和OO关注的问题域的角度不同,两者进行抽象的
方式不同,纯粹以OO进行设计的程序,会造成我前文中所提到的诸多弊端,如果能够辅以
GP思想,能够大大提高程序的可维护性、可扩充性、可复用性

总之……算了不多说了,要看球去了,呵呵
 
Y

yysun

Unregistered / Unconfirmed
GUEST, unregistred user!
在 GP 的重要性方面,大家完全一致的嘛。只是实现的方法上有些理解不同。

VB 可以把 GP 的思想,例如类型无关的 Collection,固定到类里去,
Delphi 的 TList 也是这样。Java 中用了 interface 实现这个思想。
C++ 中可以象 Delphi 那样做,因为 C++ 有纯虚拟类和多重继承。但是它并没有这么做,
而是使用了它的法宝 template。

我的观点很简单:要把 GP 应用到 Delphi:
1、固定到类里去的做法已经有了如 TList,
2、用 ADT 基本上是模仿 C++ 的纯虚拟类,应该考虑为什么 C++ 没有这么做?
RTTI 只是个补丁而已。
3、因为没有 C++ 的 template ,唯一可行的只能参照 Java,用 interface了。

回答我上面自己的选择题:A B 已经有了, D 做不到,只能选 C 了。
而 ADT + RTTI 可能是已经被 C++ 抛弃的东西,所以列也不列出来了。
 
F

flier

Unregistered / Unconfirmed
GUEST, unregistred user!
ai...真不知道你为何会有“RTTI 只是个补丁而已”这种想法,
也许对C++这种半路出家的OO语言来说的确如此,但对于其他“基础”
比较好的语言来说,RTTI实在是太重要的特性了,特别是随着语言
本身的发展,RTTI的重要性与日俱增,当然名字也许不会叫RTTI
例如叫Reflection什么的。你如果留心目前新的语言的发展方向
就会发现,无论单根类树也好,RTTI也好都是语言发展的大方向

C++里面原来也是没有RTTI的,后来实在不行才加上支持,到现在
为止仍然不是很好用。而新型的语言无论java也好C#也好CLR也好
都提供了非常强大的动态类型管理功能,都是基于单根类树,为什么?
你想过吗?难道那些语言的设计师都是白痴,专门拣C++的补丁用?

另外ADT或者说OB在C++中的重要性绝对不亚于OO,STL库可以说就是
ADT或OB编程思想的最好体现,你不能边用他边说别人被抛弃啊

过程也好,ADT/OB也好,OO或者GP也好,从来就没有谁取代谁
谁抛弃谁的问题,就算java那种所谓的先进语言,也要拿出一些
看似OO实际根本就是为了迁就其他模型的语法特性出来才行

我觉得你有点唯C++主义了,C++的确是一门出色的语言,我也非常
喜欢他,但是这并不能代表C++就没有他的缺陷,不能说他不强的地方
如RTTI就是应该抛弃的,或者说他强的地方如Template就是所有语言
必须有的,否则最后世界大同,只剩一种C++了,呵呵,可能吗?

而且C++里面为了保证C的兼容性以及效率等方面的问题,有很多
作为一个语言来说不干净的地方,我就不多说了,免得你生气,呵呵

另外,我总算体会到为什么你非要说template是GP的必须组成部分
因为你根本就是先假设了GP就是C++的实现这一条件,在这一条件下,
无论我怎么说,到你那里都变成了如何如何模仿C++了:) 这样一来
当然我怎么说你都觉得不好,因为模仿永远不可能和原来一样,
除非两者语法一致,那就变成一个语言了。

而我的前提假设就是,GP是一种思想,C++只是一种实现,这样一来
Delphi的实现和C++实现处于同等地位,两者通过不同方法实现GP
思想,因此才有我前面几篇文章的观点。而你的思路,好像根本就
只是在讨论C++实现的GP,而不是GP本身,当然会和我出现分歧。
 
Y

yysun

Unregistered / Unconfirmed
GUEST, unregistred user!
flier, 这么晚还在网上?用美国时间?
又被你抓住个把柄:“RTTI 只是个补丁而已”。

赶紧需要申明一点:“RTTI 只是个补丁而已”,“ADT + RTTI可能是已经被 C++ 抛弃”
这两点是针对 C++ 实现 GP 采用了 template, 而没有推崇 ADT + RTTI 的方案 而言。
并不是指 RTTI 技术是不好的东西。表达不清,罪过,罪过。[:(]

你最后总算明白了:“根本就只是在讨论C++实现的GP”在 Delphi中“模仿永远不可能和
原来一样”。这就是我的意思。[:D] 上面 cheka,mikedeakins,PENGS 等诸大虾,也是
这个意思啊。

就是不知道左兄死到哪儿去了?
 

左轻侯

Unregistered / Unconfirmed
GUEST, unregistred user!
这两天正在狠打盟军敢死队II,没顾得上论坛
为什么这种讨论最后总会出现唐僧VS唐僧的局面呢……
 

程云

Unregistered / Unconfirmed
GUEST, unregistred user!
有所得面有所失
 
T

Tense

Unregistered / Unconfirmed
GUEST, unregistred user!
说点题外话,请不要介意:(因为这里人气足)
不知热点问题如何划分的。
推荐下我的问题,主要是如何“划分事务机制”的。
http://www.delphibbs.com/delphibbs/dispq.asp?lid=644423
建议:yysun把这个问题讨论一下。
谢谢!
 
B

bigroom

Unregistered / Unconfirmed
GUEST, unregistred user!
精彩啊![:D]
 
F

flier

Unregistered / Unconfirmed
GUEST, unregistred user!
To yysun:
回文章时刚刚看完球,玩了把CommandosII,呵呵,习惯熬夜了
我觉得在理解一个技术时,应该站在比技术高一个层次来理解,
才能更加全面、整体地把握他。就像了解STL或者说GP在C++实现
我觉得应该首先对GP有整体理解,然后看GP在C++里面如何实现,
为什么这么实现,这么实现有什么好处,坏处,有什么别的解决方法
其他方法和现有方法的优劣在哪里;而不是应该纯粹把实现当作全部,
只盯着现有技术实现,忽略其背后的思想。要是你这么学习语言,当初
学JDK到现在就要吃好几个大弹子,呵呵
以我理解,C++之所以选择不用rtti来实现,是因为C++的特殊情况
决定的。首先是效率,对Delphi/java这样的语言来说,效率可能不是
第一考虑因素,而C++相对新兴语言最大的优势之一就是其效率,他必须
保证这个优势的延续性,因此选择template这种编译期的技术,牺牲了
灵活性,增加了编程的复杂度;第二是兼容性,C++为了提供对以前的兼容,
保留了很多不很干净的特性,比如其类树不可能改造成为单根等等;
其三是语言本身的问题,C++不断发展,但有其强项有其弱项,比如对RTTI
的支持虽然在发展中加入了支持,但到现在仍然很弱(相对其他语言),
以现有的RTTI实现GP不容易,而且违背第一条原因;最后,是设计思想,
C++设计时更注重编译期绑定,而Delphi/java则更注重运行期。前者效率高,
大部分工作在编译时已经完成了,后者则注重灵活性,可配置性,
这也是为什么C++在实现Serializable时那么麻烦的原因,
而后者在现今的应用发展处于主要地位,java当年抨击c++的很重要一条
理由就是这方面。当年MS之所以大力推COM,就有解决这方面的问题的打算
可惜COM中这方面的实现也很麻烦,呵呵
因此根本不能说谁好谁坏,如果你一定抱住C++的GP实现不放,我也没
什么办法,因为我们这里谈的是“gp在Delphi里的实现”,我一直以来写程序
也从来没有说去模仿什么C++的实现,只是通过C++的实现去揣摩gp的思想,
然后以Delphi来实现这种思想的映射而已。

btw:子曰:有把柄可抓,不亦乐乎。呵呵

To 左轻侯:
你倒是轻松啊,弹子丢出来就去玩游戏了,我们这里唾沫横飞
你在那里偷着乐啊,呵呵,不如你再看个话题“范型编程思想在
CommandosII里的应用”好了 :)
 
M

mikedeakins

Unregistered / Unconfirmed
GUEST, unregistred user!
>> 以我理解,C++之所以选择不用rtti来实现,是因为C++的特殊情况
>>决定的。
另一方面,大家仔细想想,RTTI 真的能够替代模板?说这种话的人不是
白痴就是别有用心。(我前面的回答)
 
D

dream_soft

Unregistered / Unconfirmed
GUEST, unregistred user!
大家不要乱猜了:)原因很简单,在STL实现的时候,Template已经是成熟的技术了,但
RTTI好像还没引入吧。其实并没有选择的问题。[:D]
开玩笑呢。如果不是离题太远的话,我倒想问问flier兄,"C++为了提供对以前的兼容,
保留了很多不很干净的特性,如类树不可能改造成为单根",这是事实吗?不过这也落入
"有把柄可抓,不亦乐乎"中了。[:D][:D]
我想大家还是不要离题太远,先各自用几句话写出自己对GP的准确定义,这样讨论才有
一个坚实的起点,不然就成为自说自话了。
 
Y

yysun

Unregistered / Unconfirmed
GUEST, unregistred user!
to 左兄:唐僧VS唐僧是必然的,大家英雄所见略同。有时表达不好,误会而已。
再说,这些大虾,脑子多好使,有点思想火化,查查资料,很快都上正路了。

to flier,
我在上面的第一贴中就写了:“C++中用模板的这种方法脱颖而出的原因”
1、它是编译期技术,这种方法出来的代码效率很高。
2、C++ 版本繁多、模板比类库更加通用,更加容易得到不同编译器的支持。
3、C++ 的祖师爷把模板作为实现C++旨在出效率的重要手段。
并建议大家看看这个:http://www.delphibbs.com/delphibbs/dispq.asp?lid=642717

我们要认识到 Delphi/Java 在 template 发面的差距,不能视而不见,也不能生搬硬套
去模拟。因为本质相差太大。我着重宣传的观点是:不要模拟;不要ADT+RTTI。

但是,我们也应该看到 Delphi/Java 具有 C++ 没有的特征:interface。这是个比较优
越的地方,上面推荐的 C++ 的祖师爷的问答里,他也承认。Java 中已经使用 interface
来实现 GP 思想,如其 Collection Framework。Delphi 中刚刚有了这个新玩意儿。
我并没有“抱住C++的GP实现不放”。这是我反复强调的观点是:
在 Delphi 中用 interface 来实现 GP。

dream_soft 兄提出的“自己对GP的准确定义”,我上面早就向 flier 兄提出了:
“指出您的准备用到 delphi 的 Concept 到底是哪几个概念。我看看接口是否真的做不了。”

呵呵,我还是玩 RA2,场面大些 [:D]
 
F

flier

Unregistered / Unconfirmed
GUEST, unregistred user!
to mikedeakins:
我前面文章里的观点已经很清楚了,无论是思想也好技术也好,基本上不会出现
谁取代谁的问题,只是应用的问题域不同罢了,RTTI也好Template也好,能抓住老鼠
就是好技术,按你的思路,我也可以来一句“另一方面,大家仔细想想,
模板真的能够替代RTTI?说这种话的人不是白痴就是别有用心。”:)

to dream_soft:
"C++为了提供对以前的兼容,保留了很多不很干净的特性,
如类树不可能改造成为单根"这句话我以为的确是实事,倒是后半句你可以做些文章
但是在怎么做,文章也是逻辑上的文章,你不可能像Delphi那样从编译器一级
限定单根类树的机构,因此我有以上言论。至于前半句,C++的作者如是说
至于GP的定义,我想前面已经说得够多了,之所以发了这么多文章,原因在于
两方一个是讨论GP,一个是讨论GP在C++中的实现技术,所以……hehe

to yysun:
那篇文章的确是经典,我也看过N遍,其实我从头到现在就没有反对C++中
用Template实现GP,而且在C++中这么做的确最好。我反驳的是GP不应该跟
GP在C++中的实现技术相混淆,也就是说,即使在Delphi中实现GP,也不存在
什么模仿的问题。你在讨论Delphi的地方发表“不要模拟;不要ADT+RTTI”的
言论,而没有加上一个“在C++中”的前缀,本身就容易引起误解,
Template的实现和ADT+RTTI的实现地位是平等的,都是GP思想的一种映射而已
我想你不会否认这个观点吧。既然两者不同,必然有各自的长处和短处。
ai...讨论这么长时间,好像偏题越来越远了...:(

btw:RA2电脑太弱智了,听说又出了个什么《尤里的复仇》也不知怎么样
CommandosII的操作性太复杂了,n个热键……
 
O

OopsWare

Unregistered / Unconfirmed
GUEST, unregistred user!
确实精彩,看的专著,竟然忘记事先断开拨号了[:(]...

顺便请教一下:COM 中 VTable 与你们谈的是否有关?
 

左轻侯

Unregistered / Unconfirmed
GUEST, unregistred user!
猗欤盛哉!
先结束了,以后再慢慢谈
没精力分配分数了,简单地为前20个人每人加了10分,对其他人说声对不起了
 
顶部