我使用Delphi,但这个问题我认为对任何面向对象的编程语言都有效。
什么时候我应该使用记录而不是对象。 我曾经认为,当你有一些简单的定义,你想把一组相关的数据存储在一起,不需要能够自己操作的时候,你就会使用记录。然而每当我决定一个数据应该和其他数据一起放入一个记录时,我就会想出理由来解释为什么它应该是一个完全成熟的对象。
事实上,我最近得出的结论是,在现代应用程序中,唯一应该使用记录而不是对象的时候,可能是你从磁盘上读取一个二进制文件,可以直接读到一个记录数组中。
我继承了一个有10年历史的项目,这个项目广泛使用记录而不是对象来处理小块数据,我想知道这只是我的想法,还是应该把这些概念归入经验的回收站。
讨论一下吧。
当没有方法作用于你的数据时,大部分时间是没有用的。所以你说的没错。
对象和记录之间最大的区别之一是,记录默认在堆上,而对象在堆上。要把一个记录放在堆上,你会遇到所有你提到的麻烦,但是当你可以把它们留在堆上的时候,管理对象的生命周期就容易多了。但是让我们面对现实,短命的记录没有什么用处。
当对象被实例化的时候,发生的事情不仅仅是保留内存,还有一个VMT需要管理,而记录没有。因此,分配对象比分配记录要贵一些,但我想当你不是在谈论几千个项目时,这一点是可以忽略的。
要做出选择,你需要考虑你将如何使用这些对象或记录。如果你要读取大的二进制文件,记录是最好的选择(将整个缓冲区读取到一个记录数组中,也许将它们转换为对象来使用)。如果你要处理结构化数据,我们的运行时生成的数据对象似乎更容易处理。
如果你真的只是在处理数据的情况下,那么我认为使用记录就可以了。
一些典型的场景。
然而,正如你所指出的,这些场景在典型的OO应用中是少数。
你可以在一个所谓的recordobject中一起使用记录&对象,这样做的好处是可以有效地处理数据,例如一个巨大的整数加密盒子,我们用这些封装在记录中的对象得到了更多的速度和事务。
TKeyObjAB= record
ID:string;
n:TInteger; {the modulus}
phi:TInteger; {Totient phi=(p-1)*(q-1)}
e:TInteger;
d:TInteger; {private key if e relative to phi,
which means that d*e mod phi = 1}
blocksize:integer;
keysize:Integer; {bits in modulus}
benchmark: string; //double;
end;
然后你用两个或多个recobj's来实例化它。
var
tAlice:TKeyObjAB;
tBob: TKeyObjAB;
构造函数是一个简单的函数来初始化你的成员。
function Obj_createAB(newid:string;
newkeysize:integer; actor:TKEYObjAB):TKeyObjAB;
begin
with actor do begin
id:=newid;
keysize:=newkeysize;
n:=TInteger.Create(0);
phi:=TInteger.Create(0);
e:=TInteger.create(0);
d:=Tinteger.create(0);
benchmark:= '';
end;
result:= actor;
end;
// invoke instances
talice:= Obj_createAB('Alice', 256, talice)
tbob:= Obj_createAB('Bob', 512, tbob)