Recent

Author Topic: Class Casting wont work  (Read 343 times)

kaedusoft

  • New member
  • *
  • Posts: 9
Class Casting wont work
« on: September 19, 2019, 05:51:33 pm »
Hi people. I have this question:

I have defined 3 classes, one decsends from another:

Code: Pascal  [Select]
  1. type
  2.  
  3. Class1= class ... end;
  4.  
  5. Class2= class(Clas1) ... end;
  6.  
  7. Class3= class(Clas2) ... end;

Next, I have a function like this;

Code: Pascal  [Select]
  1. function myFunction(data: Class1): boolean;
  2. begin
  3.  
  4. if data is Class3 then ....
  5.  
  6. else if data is Class2 then ...
  7.  
  8. else if data is Class1 then ...
  9.  
  10. end.

So, this code doesn't work. Each is operator returns false. Why?

The call to the function, in the main program is:

Code: Pascal  [Select]
  1. var
  2.     d1: class1;
  3.     d2: class2;
  4.     d3: class3;
  5.  
  6. begin
  7.     d1:= Class1.Create;
  8.     d2:= Class2.Create;
  9.     d3:= Class3.Create;
  10.  
  11.     myfunction(d1);
  12.     myfunction(d2)
  13.     myfunction(d3)
  14. ...
  15. end.

How can I knows the class type of data on runtime.

Thanks.
« Last Edit: September 19, 2019, 06:08:14 pm by kaedusoft »

lucamar

  • Hero Member
  • *****
  • Posts: 2020
Re: Class Casting wont work
« Reply #1 on: September 19, 2019, 06:16:29 pm »
Should work if data is any of those classes. Just in case, try this to test what is being passed:

Code: Pascal  [Select]
  1. procedure ShowClassOf(AnObject: TObject);
  2. begin
  3.   if not Assigned(data) then
  4.     ShowMessage('Not assigned to any object')
  5.   else
  6.     ShowMessage('Is a ' + AnObject.ClassName + ' object');
  7. end.
  8.  
  9. function myFunction(data: Class1): boolean;
  10. begin
  11.   ShowClassOf(data)
  12.   if data is Class3 then ....
  13.  
  14.   else if data is Class2 then ...
  15.  
  16.   else if data is Class1 then ...
  17.  
  18. end.

How can I knows the class type of data on runtime.

Check the documentation for TObject; it has some class functions to get this type of information: ClassType, ClassInfo, ClassName, etc.

Quote from: "reference for unit 'System' (RTL)
TObject introduces class methods that deal with the class' type information, and contains all necessary methods to create an instance at runtime, and to dispatch messages to the correct method (both string and integer messages).
« Last Edit: September 19, 2019, 06:28:02 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.2/2.0.4  - FPC 3.0.4 on:
(K|L)Ubuntu 12..16, Windows XP SP3, various DOSes.

Handoko

  • Hero Member
  • *****
  • Posts: 3158
  • My goal: build my own game engine using Lazarus
Re: Class Casting wont work
« Reply #2 on: September 19, 2019, 06:20:22 pm »
Not sure but I saw something not 'very' correct:

Code: Pascal  [Select]
  1. type
  2.  
  3. Class1= class ... end;
  4.  
  5. Class2= class(Clas1) ... end;
  6.  
  7. Class3= class(Clas2) ... end;
end.[/code]

It should be:
Code: Pascal  [Select]
  1. type
  2.  
  3. Class1= class ... end;
  4.  
  5. Class2= class(Class1) ... end;
  6.  
  7. Class3= class(Class2) ... end;

lucamar

  • Hero Member
  • *****
  • Posts: 2020
Re: Class Casting wont work
« Reply #3 on: September 19, 2019, 06:29:10 pm »
Not sure but I saw something not 'very' correct

[...]

Probably a typo when editing the post; otherwise it wouldn't compile, would it?
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.2/2.0.4  - FPC 3.0.4 on:
(K|L)Ubuntu 12..16, Windows XP SP3, various DOSes.

kaedusoft

  • New member
  • *
  • Posts: 9
Re: Class Casting wont work
« Reply #4 on: September 19, 2019, 06:44:30 pm »
Should work if data is any of those classes. Just in case, try this to test what is being passed:

Code: Pascal  [Select]
  1. procedure ShowClassOf(AnObject: TObject);
  2. begin
  3.   if not Assigned(data) then
  4.     ShowMessage('Not assigned to any object')
  5.   else
  6.     ShowMessage('Is a ' + AnObject.ClassName + ' object');
  7. end.
  8.  
  9. function myFunction(data: Class1): boolean;
  10. begin
  11.   ShowClassOf(data)
  12.   if data is Class3 then ....
  13.  
  14.   else if data is Class2 then ...
  15.  
  16.   else if data is Class1 then ...
  17.  
  18. end.

How can I knows the class type of data on runtime.

Check the documentation for TObject; it has some class functions to get this type of information: ClassType, ClassInfo, ClassName, etc.

Quote from: "reference for unit 'System' (RTL)
TObject introduces class methods that deal with the class' type information, and contains all necessary methods to create an instance at runtime, and to dispatch messages to the correct method (both string and integer messages).

External: SIGSEGV occurs when AnObject.ClassName called. Its very very strange.

wp

  • Hero Member
  • *****
  • Posts: 6233
Re: Class Casting wont work
« Reply #5 on: September 19, 2019, 07:03:02 pm »
These code snippets are very difficult to check because we do not see what else you are doing. Here is a compilable example based on your code and that of others in this thread, and this is working. Compare what is different in your case.
Code: Pascal  [Select]
  1. program Project1;
  2.  
  3. type
  4.   TClass1 = class(TObject);
  5.   TClass2 = class(TClass1);
  6.   TClass3 = class(TClass2);
  7.  
  8.   procedure ShowClassOf(AnObject: TObject);
  9.   begin
  10.     if not Assigned(AnObject) then
  11.       WriteLn('Not assigned to any object')
  12.     else
  13.       WriteLn('Is a ' + AnObject.ClassName + ' object');
  14.   end;
  15.  
  16.   function myFunction(data: TClass1): Integer;
  17.   begin
  18.     if data is TClass3 then
  19.       Result := 3
  20.     else if data is TClass2 then
  21.       Result := 2
  22.     else if data is TClass1 then
  23.       Result := 1
  24.     else
  25.       Result := -999999;
  26.   end;
  27.  
  28. var
  29.   d1: TClass1;
  30.   d2: TClass2;
  31.   d3: TClass3;
  32.   c: TObject;
  33. begin
  34.   d1 := TClass1.Create;
  35.   d2 := TClass2.Create;
  36.   d3 := TClass3.Create;
  37.   c := TClass.Create;
  38.  
  39.   WriteLn(myfunction(d1));
  40.   WriteLn(myfunction(d2));
  41.   WriteLn(myfunction(d3));
  42.   WriteLn(myfunction(TClass1(c)));
  43.  
  44.   ShowClassOf(d1);
  45.   ShowClassOf(d2);
  46.   ShowClassOf(d3);
  47.   ShowClassOf(c);
  48.  
  49.   ReadLn;
  50. end.

Output:
Code: [Select]
1
2
3
-999999
Is a TClass1 object
Is a TClass2 object
Is a TClass3 object
Is a TObject object
« Last Edit: September 19, 2019, 07:04:36 pm by wp »
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

Handoko

  • Hero Member
  • *****
  • Posts: 3158
  • My goal: build my own game engine using Lazarus
Re: Class Casting wont work
« Reply #6 on: September 19, 2019, 08:17:32 pm »
@kaedusoft

When asking about problem related with the coding, it always good to provide the 'real' code. If you're not willing to publicize the whole source code, you can create a demo that showing the issue.

Create a new folder, copy and paste all the necessary files except: the binary (exe file), *.bak, lib and backup folders. Compress the folder and send the zip here.

Probably a typo when editing the post; otherwise it wouldn't compile, would it?

I knew. I did it intentionally to show how important providing the compile-able source code when asking such question, which can really reduce the time for others and no more guessing: Help others to help you.
« Last Edit: September 19, 2019, 08:19:14 pm by Handoko »

kaedusoft

  • New member
  • *
  • Posts: 9
Re: Class Casting wont work
« Reply #7 on: September 19, 2019, 08:26:28 pm »
SOLVED...

I had forgotten to use overload keyword when defining the constructor of the first class (Class1 in this example).

Thank you very much everyone for your time and dedication.

NOTE: The real code is too large, uses units, databases and much more... I simplify de code for help you... so I should have put the definition of builders.
« Last Edit: September 19, 2019, 08:37:24 pm by kaedusoft »