On 26.09.2013 08:39, Xiangrong Fang wrote:
Hi All,
I have the following program:
1 program test;
2 {$mode objfpc}{$H+}
3 uses tree;
4 type
5 TIntTree = class(specialize TTree<Integer>)
6 public
7 function Clone: TIntTree;
8 end;
9 function TIntTree.Clone: TIntTree;
10 begin
11 Result := TIntTree(inherited Clone);
12 end;
13 var
14 it1, it2 : TIntTree;
15 begin
16 it1 := TIntTree.Create(1, nil);
17 it2 := it1.Clone;
18 WriteLn(it1.ClassName);
19 WriteLn(it2.ClassName);
20 end.
Which output:
TIntTree
TIntTree.TTree$LongInt
The source code of TTree is here:
https://github.com/xrfang/fpcollection/blob/master/src/units/tree.pas
Why the typecast on line 11 does not work? How to modify the code so
that the cloned object has same type as the original one?
Please always think through this without generics.
Your code looks roughly like this:
=== code begin ===
type
TTreeInteger = class
function Clone: TTreeInteger;
end;
TTreeInt = class(TTreeInteger)
function Clone: TTreeInt;
end;
function TTreeInteger.Clone: TTreeInteger;
begin
Result := TTreeInteger.Create;
end;
function TTreeInt.Clone: TTreeInt;
begin
Result := TTreeInt(inherited Clone);
end;
=== code end ===
As you can see you are constructing a TTreeInteger class inside
TTreeInteger.Clone and nothing in the world afterwards can turn it into
a TTreeInt. If you'd use the "as" operator in TTreeInt.Clone then you'd
even get an exception, because you can not assign a TTreeInteger
instance(!) to a TTreeInt.
What should work is the following (now with generics again):
=== code begin ===
type
TTree<T> = class
private type
TSelfClass = class of TTree;
public
function Clone: TTree;
end;
function TTree.Clone: TTree;
begin
Result := TSelfClass(Self.ClassType).Create(Data, FParent);
(* ... *)
end;
=== code end ===
Note: The cast to TSelfClass is necessary to have access to the
overloaded constructor you added for TTree<>.
Regards,
Sven
_______________________________________________
fpc-pascal maillist - fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal