为什么 Java 要采用 C++ 的构造模式而不是 Delphi 的?!(50分)

再次声明:构造函数不是用来分配内存的,分配内存的工作在此函数被
调用前就完成了.
所以叫"构造"有点不确切.
在Delphi中构造一个对象也可以分两步进行:比如TApplication
的CreateForm方法:
procedure TApplication.CreateForm(InstanceClass: TComponentClass;
var Reference);
var
Instance: TComponent;
begin
Instance := TComponent(InstanceClass.NewInstance);
//这个才是分配内存
TComponent(Reference) := Instance;
try
Instance.Create(Self);
//显示的调用构造函数,C++中不允许这样做
except
TComponent(Reference) := nil;
raise;
end;
.......
还要注意到 InstanceClass 也是Object Pascal 中特有的类引用类型(Class Refrence)。
它可以实现虚构造函数,这个在C++ 里也是没有的.C++要实现动态生成只能使用宏的
方式.
 
to James Martin:
2083287,我是指楼上“洗衣机”那个帖子。没说清楚,再加上我刚来大富翁还是一个菜鸟:(
关键是我没有理解Delphi的继承机制,望文生义,再加上有一两个Delphi高手表现出来的
OOP水平和我的想象有差异,一时兴起吵了一架,对不起大家了,真的,说老实话,我现在
真的不知道对Delphi的理解是不是错了,但对简单的一些OOP知识,我还是有一点信心的。

to 李大嘴:
C++也是一种混合语言,但他的OOP部分在严格遵循OOP原则的,这一点我从C转为C++时有过
痛苦的经历的;而我很少见到由C转为Delphi的摔键盘、扔鼠标的,反而是眉开眼笑的,我
打心眼里羡慕!从我在上面望文生义的理解来看,Delphi在OOP部分居然也是允许混合的,
原来如此!
我从来都没有说谁优谁劣啊!Delphi很优秀,诸位Fans放心吧!
另外,这大热的天儿,你叫我凉快去,真的谢谢你!
佩服你,仰慕你,要是以我的性格,现学现卖都要干上一架,输了也长了见识,再嗑几个头
拜一下师,不就是赚大了?网上又没人认识我李大嘴。对不对?
 
阅!!!
 
这个问题有什么好吵的吗?
真是服了,不就是开发JAVA的哪几个家伙用C++/C用的熟一些,选自己最习惯的语言
做为蓝本,这就是原因.
 
这么热的天,看来大家都是在空调房间里吵,不然哪来如此激情??
 
吵什么吵啊,赋值、循环、判断、跳转、加法、IN/OUT解决一切问题!JAVA那是吹出来的!!
 
to wuliaotd
我说怎么现在很多人容易吵起来,
原来很多都是象你这么想, 给人说了明知自己不对了也"现学现卖都要干上一架,输了也长了见识",完了还来几句
>>> "我知道,你们就会点Delphi,每月也拿一千多不容易啊,所以容不得人说Delphi的半点不是。"
还真是伶牙俐齿,骂得真够宽的,难怪这里气氛越来越不友好,不象以前技术讨论就技术讨论.
把你说过的话删掉跟DELPHI无关的和磕头认错的,看有几句是成立的?
"东西没有完全理解之前",还是多看多听少说的好,至少可以让DELPHIBBS少出现几个错别字.

 
to 李大嘴:
“给人说了明知自己不对了”???
我都不想教育你了,就算理论上的争论是萝卜白菜各有所爱,但具体问题上我是对啊!别忘
了楼主问的是一个Java问题。我不懂就是不懂,不会不懂装懂。通篇看完,绝大多数人至少
不会认为我是无理取闹,至少还有那么一点东西。
唉,我不对又怎么样,要死个人吗?我在帖子中给自己丢脸了吗?我错了,我错了,我错了,我错了,我错了,我错了!!!!你满意了吗?你要精神胜利容易得很,我给你就是。
>>> "我知道,你们就会点Delphi,每月也拿一千多不容易啊,所以容不得人说Delphi的半
点不是。" ------各位仁兄,这种人多不多呢?

to xeen:
真诚的讨教:
不知你同不同意我的观点(不是孰优孰劣的问题):
-------------------------------------------------
C++也是一种混合语言,但他的OOP部分在严格遵循OOP原则的,这一点我从C转为C++时有过
痛苦的经历的;而我很少见到由C转为Delphi的摔键盘、扔鼠标的,反而是眉开眼笑的,我
打心眼里羡慕!从我在上面望文生义的理解来看,Delphi在OOP部分居然也是允许混合的。
-------------------------------------------------
我的观点对吗?比如我仿佛记得(我只在几年前用过一下Delphi),在var代码段中还可以
有其它变量(是不是?),如果是的话,那么你用:
Instance := TComponent(InstanceClass.NewInstance);
//这个才是分配内存
TComponent(Reference) := Instance;
创建实例,分配内存,其它变量存在于那里?属于哪个对象?好象这个实例变量与其它变量
是一个平行的关系,对不对?
我从这里理解也感觉Delphi和VB很相似(表单变量和全局变量),主要是面向过程的。

 
现在关于newInstance的探讨才真正的到了问题的关键, 为什么delphi里有virtual constructor, 这主要是由于delphi的MetaClass的实现方式决定的.
在java和delphi里都支持MetaClass, 但实现的方法不同.
在java中, MetaClass采用反射机制来实现MetaClass, 例如
Class metaClass = forName("MyClass");
MyClass MyObj = (MyClass) metaClass.newInstance();
而delphi是采用class reference和virtual constructor配合来实现的, 例如.
TComponentClass = class of TComponent
..
MyObj : TComponent;
myClass : TComponentClass ;
RegisterClass("MyClass");
..
myClass:= FindComponentClass("MyClass");
MyObj := myClass.Create(nil);
-- override constructor
对于class reference, delphi帮助如下
class reference is an expression that refers to a specific class. A class reference is not quite a first class object, as it is in Java or Smalltalk, but is used to create new objects, call class methods, and test or cast an object's type. A class reference is implemented as a pointer to a table of information about the class, especially the class's virtual method table (VMT).
由上我们可看出, delphi不象java 或C#, 他不是基于VM的, 所以他不可以象java通过JVM来帮助实现反射, 对与class reference和virtual constructor配合的方法好坏, 我不好评说, 但基于VM的运行语言已成为趋势, delphi.net已经在利用.net的特性, 完成了这个飞跃.
另外, JVM和.net的VM也有很大不同, 下面是他们在执行中的主要区别.
Executing interpreted code means: for each opcode in the input stream,
collect the parameters to the opcode and call a chunk of native code to
perform the operation represented by the opcode. Think of it as a giant
case statement inside the interpreter. Every time execution passes through
an interpreted function, the meaning of the opcode is evalutated anew.
Executing native compiled code means: each opcode in the input stream is
recognized by the CPU hardware and the operation corresponding to the
symbolic opcode is performed by the CPU hardware.
.NET IL bytecode is compiled into native machine code when it is loaded from
disk into memory. .NET applications run native compiled code.
.NET is different from Java in that Java was first designed to be
interpreted, and later Just In Time compilation was added. Even in a fully
"JIT'd" Java platform, there exists a Java bytecode interpreter somewhere in
the VM. In .NET, there is no IL bytecode execution interpreter. .NET IL
code is always compiled to native code before it executes.
The compiler you refer to is part of the program loader. You compile your
Delphi source code into a .NET executable using the Delphi for .NET
compiler. You then
run your .NET program Hello.exe, and the program loader
takes care of "compiling" the machine-independent .NET code in your program
into native machine code as your program makes calls to subroutines.
The advantage of this approach is that your Hello.exe program has the
potential to run on different CPU architectures - Intel 32 or 64 bit, AMD 64
bit, Motorolla, even Fujitsu mainframes.


 
~
[h4]请教楼上深刻掌握面向对象思想高手们:
面向对象的思想用最精简的话概括出来该怎么说??
诚心讨教(注意精简概括四字)[/h4]
 
//Instance := TComponent(InstanceClass.NewInstance);
//这个才是分配内存
//TComponent(Reference) := Instance;
//创建实例,分配内存,其它变量存在于那里?属于哪个对象?好象这个实例变量与其它
//变量是一个平行的关系,对不对?
//我从这里理解也感觉Delphi和VB很相似(表单变量和全局变量),主要是面向过程的。
仅凭这个就下结论,是不是不太严谨啊?[:D] 你看那这段代码呢:
BOOL CTestApp::InitInstance()
{
...
// “其他变量”
int i = 0;
// 创建实例,分配内存
CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(...);
...
}
这么说 C++ 的“实例变量与其它变量”也“是一个平行的关系”啰?
就是说 C++ 也是“面向过程的”的啰?[:D]
还有,delphi 支持多态,VB 不行吧,而如果一种语言不支持多态,
那么我们说他不支持面向对象,不为过吧?[:)]

 
我也想加入几句,再说说我观点:
首先,排除 VB,至少,在它的历史过程中一直是“伪对象”支持,虽然现在
的 VB 可能正如 wuliaotd 所说的“浴火重生”,但我不了解,所以不讨论它。
就三种语言:C++, Delphi, Java 我说一下我的看法。

1、三种语言都实现了对象支持,在语法上,有一些差别:

·C++ 对对象的支持最广泛,如:它支持从一个 struct 派生,并且,在一个
struct 内也可以包含成员方法(不过全是 public);Delphi 不支持,在它的语法
规则中,一个 Record 就是一个 Record, 一个 Object 就是一个 Object(现在叫 class);
Java 全是类,没这些特性。
·类的继承。C++支持多重继承,并且由于它支持 struct 的派生,因此也存在
多根继承;Delphi/Java 都只支持单根继承,但可实现多个 Interface。从覆盖的
范围来讲, C++ 更广义一些。
注:本人意见,从这点也可以看出,C++ 在其实现过程中,更多地参考了“完全”
对象的思想,但由于需要“兼顾”原来的 C,使得 C++ 在其行为特征上,有了许多
“奥妙无穷”的变化。
·类的封装。无论什么语言,只要支持类,支持继承,支持 public/protected/private,
以及 virtual(dynamic 只是 delphi 所有,所以可归入 virtual), abstract, override,
封装只是随之而来的结果,至于封装的“完整性”,这全是商品实际的程序差别。与语言
对对象本身的支持没有关系。这只能作一个商品完美程序的考虑因素。
·特殊地,java 支持 final 机制,其它语言没有。这种机制到底为什么,我不
清楚,从某种意义上讲,它更多是为了实现一个常态的类型。
2、构造方式。C++ 总是先构造父类;Delphi 可在构造的同时选择父类的构造(inherited);
Java 从语法上来讲,是可选择的,因为它完全可以放弃 super,但如果要用 super,
就必须实现 C++ 的构造方式;Delphi 比较自由,因其根类 TObject 本身没有构造,但
三种语言全部支持默认构造(无参构造)。这里面稍有不同的是:
·Delphi 中,如果要覆盖父类的构造,那么必须提供同参构造;否则必须提供其他的
构造(至于如何继承父类的构造,则完全可以由你自己选择)。而 C++ 中,必须首先实现
父类的构造,并且是显式的,这也是 C++ 保证在子类构造前,它的父类必须先被构造的唯
一措施;Java 没有显式强制,但如果要继承,则必须是第一个有效代码前调用 super,这
与 C++ 的强制有类同之处,但它似乎在支持一个能够完全覆盖父类的构造模式:即完全不
调用 super。Java 采用这种方式,直接隐含了一个处理:继承构造非必须。这有什么意图?
如果有人要说安全,实际上,如果父类的某些信息(当然是初始化例程)是必须的,这种
方式就可以说是严重不安全,甚至编译都无法通过;或者运行直接异常。Java 引入这种机
制与 Java 强调的“安全”似乎格格不入,更多的似乎是为“重生”一个类系而服务。但
这与对象编程中有效的“继承”违背!并且从某种角度来讲,也是非常不安全的。就是这一
点,引起了我举出的例子无法通过编译的原因 ---------- 我的看法。
至于更多的特性,在我看来,三者实现几乎没有什么更多的差异。唯一的就是:C++/Delphi
需要考虑历史的兼容;而 Java 则是完全重新设计。函数处理是遗留问题,我想也没有必要
去多追究了吧。
3、综上,这三种语言都很完善地实现了对象编程的环境。至于象 wuliaotd 所说地:
如果 Delphi 失去了 VCL,就象是砍了头;而 VC 失去了 MFC 只是失了臂膀,我想这不是
比较一个语言本身的特性的基础,因为:就是 VCL 也是完全由 Delphi/Object Pascal 写
出来的,所以这些说法是完全不用考虑的 ---- 绝对是错!
4、RAD。许多人在 RAD 上面讨论、争论甚至恨不得要战争(太夸张了,^_^)。从我
个人使用情况来看,完全没有必要。RAD 简化了开发,是以后必然的趋势,就如 GUI 环境
一直为许多专家不屑,现在却成为一个操作系统的标准环境之一。方便的开发环境并不影
响你的编程方法,编程思想,而是为你能够轻松实现你的项目提供一个更舒适的环境,何
乐而不为呢?它隐藏了许多幕后的东东?如果你去读一读 VCL,你还会有如此仅浮于表面
的理解吗?记得大富翁上就有一个发过读 VCL 而发问的帖子。本人虽然没有系统地读过
VCL,但在常用的几个类,几个组件的实现上,也稍稍“深入”地研究过,并且也实现了
一些比现有的 VCL 组件更“高级”的东东。正如许多人愿意读 MFC,却把 VCL 弃之不屑,
我想不通,VCL 在委托、继承和子类化在有太多的技术可以去读,去研究,而且这也不是
一个“高中生”能够理解的(除非他是天才,别论),我的想法是:轻视一种语言,只能
表示你的虚弱,或者是虚伪。拿一句话来说:魔道殊途,至极同归。心中无剑,则无剑,
心中有剑,腐朽化神奇!
--------------------------------------------------------------------------------------
谢谢大家的参与。
 
To wuliaotd:
Object Pascal 当然不是一种纯面向对象的语言,因为它本身就是就是从面向过程
的语言演变来的.比如说它还有全局变量,简单数据类型(C++也一样)。
而且 Object Pascal 是 Heap Based,就是说所有的对象够构建在Heap上,不能象
C++那样可以构建在stack上,所以 var 段定义的只可能是对象指针:
var
aEdit:TEdit;
相当于:
CEdit* pEdit;
aEdit := TEdit.Create(nil);
相当于:
pEdit = new CEdit();

 
3、综上,这三种语言都很完善地实现了对象编程的环境。至于象 wuliaotd 所说地:
如果 Delphi 失去了 VCL,就象是砍了头;而 VC 失去了 MFC 只是失了臂膀,我想这不是
比较一个语言本身的特性的基础,因为:就是 VCL 也是完全由 Delphi/Object Pascal 写
出来的,所以这些说法是完全不用考虑的 ---- 绝对是错!
--------------------------------------------------------------------------
呵呵 VCL 与 Object Pascal 是密不可分的,至少 TObject 是. 因为 VCL类库的
实现与编译器是密切相关的。很多代码你看不到,但编译器已经暗地里替你作了.
也可以说VCL是Object Pascal语言的一部分.
MFC与 C++的关系与此不同,我知道至少 BCB的编译器就兼容MFC.
 
一晚不见,这个帖子长这么大了.真令人吃惊的.
 
"
C++ 对对象的支持最广泛,如:它支持从一个 struct 派生,并且,在一个
struct 内也可以包含成员方法(不过全是 public);
"
-------------------------------
c++ 的 struct = class,除了访问方法的默认方式不同,好像这与他的历史有关,不推荐使用。
太不严肃了,用了“好像”[:)]
 
大家不用吵了.
结贴,散分.[:D]
 
夜里还吵?厉害!
都别说了。
[gold]大道无形。[/gold]
 
也可以说VCL是Object Pascal语言的一部分.
------------------------------------------
话倒是这样说。Delphi还保留着Object Pascal的凭空产生类的方式,你完全可以跳出VCL写出自己的类库。完全不是从TObject派生的。Type
TA=Object --------》注意不是Class而是Object
private
.....
end;
PTB=^TB;
TB=Object(TA) --------》注意不是Class而是Object
.....
end;
.....
B:pTB;
new(B);
不过这样TObject很多优秀特性都没有了,都要自己去实现。就象MFC的大多数东西都是从CObject派生的一样。为什么要摒弃现成的东西自己去构造呢?
有一个著名的Delphi类库KOL就是。我公司也有一套类似的自己的类库。
面向对象和面向过程混和式有什么不好吗?Delphi和C++都是这样的。
我很讨厌Java的完全,想写一个函数却不得不构建一个类。Delphi和C++在这一点上就好多了。而且Delphi和C++赋予你很强的能力,可以干任何底层的事情,可以嵌入汇编。

再一个在C++中struct已经算不得是简单数据类型它和Class几乎完全一样,唯一不同就是struct 的成员默认为共有,而CLASS的成员默认为私有。提到这里Java还有一点讨厌就是不能自己构件简单的数据类型。这一点我更喜欢.Net。
 
to 大富翁WW:
>> 面向对象的思想用最精简的话概括出来该怎么说??
我的说法就是:委托+封装。
 
顶部