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

Reply via email to