A few days ago, I tried to make a very simple control (based on the D5 developer guide)
This control uses a class inherited from tpersistent.
Type
Tsomeobject = Class (tpersistent)
Private
Fprop1: integer;
Fprop2: string;
Public
Procedure assign (Source: tpersistent); override;
Published
Property prop1: integer read fprop1 write fprop1;
Property prop2: String read fprop2 write fprop2;
End;
.
.
.
.
Procedure tsomeobject. Assign (Source: tpersistent );
Begin
If source is tsomeobject then
Begin
Self. fprop1: = tsomeobject (Source). fprop1;
Self. fprop2: = tsomeobject (Source). fprop2;
End;
Inherited assign (source );
End;
According to the example in D5, I found that when I used assign, I always prompted tsomeobject can not assing to tsomeobject. This is
What's going on? Why does this error occur? Let's take a look at the tpersistent and other derived classes to achieve this, all of which are inherited.
Assign (source); why is my error? Later, I tried to add an exit;
Procedure tsomeobject. Assign (Source: tpersistent );
Begin
If source is tsomeobject then
Begin
Self. fprop1: = tsomeobject (Source). fprop1;
Self. fprop2: = tsomeobject (Source). fprop2;
Exit;
End;
Inherited assign (source );
End;
The error is missing. Why does inherited assign (source) fail? So I finally found the answer by checking the source code.
Because assign in tpersistent is a virtual method, there is no specific implementation
<----- Source code in tpersistent ------>
Procedure tpersistent. Assign (Source: tpersistent );
Begin
If source <> nil then source. assignto (Self) else assignerror (NiL );
End;
Procedure tpersistent. assignerror (Source: tpersistent );
VaR
Sourcename: string;
Begin
If source <> nil then
Sourcename: = source. classname else
Sourcename: = 'nil ';
Raise econverterror. createresfmt (@ sassignerror, [sourcename, classname]);
End;
Procedure tpersistent. assignto (DEST: tpersistent );
Begin
DeST. assignerror (Self );
End;
<----------------------------------->
From the source code, we can see that
Assign-> assignto-> assignerror
Whether it is assign or assignto, The assignerror method must be executed. Therefore, classes inherited from tpersistent must be overwritten.
Assign Method for tpersistent
<----- Tcollection ----->
Procedure tcollection. Assign (Source: tpersistent );
VaR
I: integer;
Begin
If source is tcollection then
Begin
Beginupdate;
Try
Clear;
For I: = 0 to tcollection (Source). Count-1 do
Add. Assign (tcollection (Source). items [I]);
Finally
Endupdate;
End;
Exit;
// Exit is used here
End;
Inherited assign (source );
End;
<------------------------->
The tstrings class is also
<----- Tstrings ----->
Procedure tstrings. Assign (Source: tpersistent );
Begin
If source is tstrings then
Begin
Beginupdate;
Try
Clear;
Fdefined: = tstrings (Source). fdefined;
Fquotechar: = tstrings (Source). fquotechar;
Fdelimiter: = tstrings (Source). fdelimiter;
Addstrings (tstrings (source ));
Finally
Endupdate;
End;
Exit;
// This is also the exit
End;
Inherited assign (source );
End;
<---------------------->
From the above, we can see that when the derived class of tpersistent overwrites the assign, the processing process that meets the conditions should be exited after the processing is completed.
, Do not go to inherited assign (source), because this will eventually be executed to assignerror