[fpc-pascal] class inheritance and type incompatibility

Sven Barth pascaldragon at googlemail.com
Sat Sep 28 18:58:59 CEST 2013


On 28.09.2013 16:37, Xiangrong Fang wrote:
> 2013/9/28 Sven Barth <pascaldragon at googlemail.com
> <mailto:pascaldragon at googlemail.com>>
>
>
>     On second sight your solution is not correct, because you are using
>     Clone inside your parent class which would not use the (non-virtual)
>     Clone you created.
>
>
> ​What If I make Clone virtual? If by adding "virtual" to Clone, the
> problem is solved, then what's the difference between virtual Clone and
> the method you provided?

If you want to override the virtual Clone method of TTree<LongInt> in 
TIntTree you need to use the same result type + override or otherwise 
you gain nothing, because the compiler will not consider the method as 
overloaded and use the Clone method of TTree<LongInt> inside 
TTree<LongInt>'s methods instead.

>>
>     === code begin ===
>
>     type
>        generic TTree<T> = class
>        private type
>          TSelfType = TTree;
>          TSelfClass = class of TSelfType; // earlier I suggested TTree
>     which 2.6.2 does not support
>
>
> ​This compiles, however, if I remove my version of TIntTree (i.e.
> implement a Clone in it and call parent's DoClone), then the main
> program does not compile, it says:
>
> demo2.lpr(20,13) Error: Incompatible types: got "TIntTree.TTree$LongInt"
> expected "TIntTree"
>
> I then can either:
>
> 1) add a Clone method to TIntTree and do a typecast inside it, as you said.
> 2) do a typecast in the main program, i.e. it2 := it1.Clone as TIntTree.

Would you please show how exactly you changed the code? With all those 
methods calling each other it's a bit hard to imagine in my head what 
you changed. ;)

>
> So, I guess the problem is solved?  I have two further questions:
>
> 1) Why class of TTree does not work in 2.6.2 but class of TSelfType
> worked? Is it a problem of generics in 2.6.2, or it is *not* related to
> generics?   I feel that TSelfType is same as TTree?

It's a problem of generics in 2.6.2. Principially TSelfType is the same 
as TTree, but the 2.6.2 compiler treats them a little bit differently.

>
> 2) What is the difference between the following:
>
> - it2 := TIntTree(it1.Clone);
> - it2 := it1.Clone as TIntTree;

The latter does a conversion at runtime, so if "it1.Clone" returns an 
instance that is not compatible with TIntTree (for example a TObject or 
a TTree<LongInt>) then an exception will be raised. The former does not 
raise such an exception (but will show you a warning if you try to e.g. 
convert a TTree<LongInt> to a TTree<String>, but AFAIK the "as" will 
show that warning as well) and does not require additional runtime code 
(thus if you know that a e.g. TTree<LongInt> variable really contains a 
TIntTree instance you can use the hard typecast). If you compile code 
with -CR or {$OBJECTCHECKS ON} then the hard typecast will be the same 
as "as".

>
> Where in the official document can I find the behavior/definition of "as"?

Here: http://freepascal.org/docs-html/ref/refsu45.html#x135-14500012.8.7 
(Chapter Expressions => Class operators)

Regards,
Sven



More information about the fpc-pascal mailing list