Bookstore

Recent

Author Topic: Inherit event procedure  (Read 375 times)

xenon54

  • Newbie
  • Posts: 4
Inherit event procedure
« on: February 25, 2020, 07:09:30 pm »
Hi, All!

Code: Pascal  [Select]
  1.  
  2. type
  3.  
  4.   TMyEvent = procedure(Sender: TObject) of object;
  5.  
  6.   TNewClass = class(TObject)
  7.  
  8.   end;
  9.  
  10.   TAClass = class
  11.     private
  12.       FOnEvent : TMyEvent;
  13.  
  14.     public
  15.       property OnEvent : TMyEvent read FOnEvent write FOnEvent;
  16.   end;
  17.  
  18.  
  19.   SomeVar : TAClass;
  20.  
  21.   ...
  22.  
  23. begin
  24.  
  25.   ...
  26.  
  27.   SomeVar := TAClass.Create;
  28.   SomeVar.OnEvent := @onEv;
  29.  
  30.   ...
  31.  
  32.   procedure TForm1.onEv(Sender: TNewClass);
  33.   begin
  34.  
  35.   end;  
  36.  
  37.  


In this example copiller shows me error

Code: Pascal  [Select]
  1. Error: Incompatible types: got "<procedure variable type of procedure(TObject) of object;Register>" expected "<procedure variable type of procedure(TNewClass ) of object;Register>"
  2.  

What to do with this?

I dont want to do any like this in any usage of this...


Code: Pascal  [Select]
  1.  
  2.   procedure TForm1.onEv(Sender: TObject);
  3.   var
  4.     a : TNewClass;
  5.   begin
  6.  
  7.     a := TNewClass(Sender);
  8.  
  9.   end;  
  10.  
  11.  
  12.  
« Last Edit: February 25, 2020, 07:25:41 pm by xenon54 »

howardpc

  • Hero Member
  • *****
  • Posts: 3356
Re: Inherit event procedure
« Reply #1 on: February 25, 2020, 09:02:35 pm »
In the declaration of TForm1 you have to declare the procedure with exactly the same signature:
Code: Pascal  [Select]
  1.   TForm1 = class(TForm)
  2.     procedure BlahBlah;
  3.     ...
  4.   private
  5.     ...
  6.   public
  7.     procedure OnEv(Sender: TObject);
  8.   end;
Only then can you write in some other TForm1 method
Code: Pascal  [Select]
  1. SomeVar.OnEvent := @onEv;
 
BTW, what you call TMyEvent is called TNotifyEvent everywhere else in the LCL.

Why the duplication?

xenon54

  • Newbie
  • Posts: 4
Re: Inherit event procedure
« Reply #2 on: February 25, 2020, 09:40:53 pm »
In the declaration of TForm1 you have to declare the procedure with exactly the same signature:
Code: Pascal  [Select]
  1.   TForm1 = class(TForm)
  2.     procedure BlahBlah;
  3.     ...
  4.   private
  5.     ...
  6.   public
  7.     procedure OnEv(Sender: TObject);
  8.   end;
Only then can you write in some other TForm1 method
Code: Pascal  [Select]
  1. SomeVar.OnEvent := @onEv;
 
BTW, what you call TMyEvent is called TNotifyEvent everywhere else in the LCL.

Why the duplication?

Thx for your reply, howardpc.

Duplication is just for example.

Maybe i m bad to understand my problem. Your reply about blahblah procedure unclear for me.

I meant that I would like to use the inherited type of class as Event param, but compiller gives me error.


Maybe a real example is better.


I use LNet component TLTcp in console application.
There is OnReceive event in this class. And as param in that procedure(event) have (aSocket : TLSocket).
I have inherited class TMySocket from TLSocket whit some new properties and methods.

And when i want to declare OnReceive event with my class as param, i got error.


I can do this
Code: Pascal  [Select]
  1. procedure TSomeApplication.OnReceive(aSocket : TLsocket);
  2. var
  3.   t : TMySocket;
  4. begin
  5.   t := TMySocket(aSocket);
  6.   ...
  7. end;
  8.  

but, its not elegant from me. Is there any way to do this right?

lucamar

  • Hero Member
  • *****
  • Posts: 2579
Re: Inherit event procedure
« Reply #3 on: February 25, 2020, 09:51:01 pm »
The problem in your first post is here:

Code: Pascal  [Select]
  1.   procedure TForm1.onEv(Sender: TNewClass);

As declared the event handler must have a TObject as parameter; otherwise you're trying to assign incompatible types.

Note that, though I advice seriously against it, you can always use absolute to hard-cast the passed object, so you could do, for example:

Code: Pascal  [Select]
  1. procedure TForm1.onEv(Sender: TObject);
  2. var
  3.   NewObject: TMyClass absolute Sender;
  4. begin
  5.   NewObject.SomeMyClassMethod();
  6.   {... etc ...}
  7. end;
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.6/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

xenon54

  • Newbie
  • Posts: 4
Re: Inherit event procedure
« Reply #4 on: February 25, 2020, 09:57:32 pm »
The problem in your first post is here:

Code: Pascal  [Select]
  1.   procedure TForm1.onEv(Sender: TNewClass);

As declared the event handler must have a TObject as parameter; otherwise you're trying to assign incompatible types.

Note that, though I advice seriously against it, you can always use absolute to hard-cast the passed object, so you could do, for example:

Code: Pascal  [Select]
  1. procedure TForm1.onEv(Sender: TObject);
  2. var
  3.   NewObject: TMyClass absolute Sender;
  4. begin
  5.   NewObject.SomeMyClassMethod();
  6.   {... etc ...}
  7. end;


And what the diference btw

Code: Pascal  [Select]
  1.  
  2. procedure TForm1.onEv(Sender: TObject);
  3. var
  4.   NewObject: TMyClass absolute Sender;
  5. begin
  6.   NewObject.SomeMyClassMethod();
  7.   {... etc ...}
  8. end;
  9.  
  10.  

and

Code: Pascal  [Select]
  1.  
  2. procedure TForm1.onEv(Sender: TObject);
  3. var
  4.   NewObject: TMyClass;
  5. begin
  6.   NewObject := TMyClass(Sender);
  7.   {... etc ...}
  8. end;
  9.  
  10.  

?

lucamar

  • Hero Member
  • *****
  • Posts: 2579
Re: Inherit event procedure
« Reply #5 on: February 25, 2020, 10:20:53 pm »
Very little. Basically you save up one line. But note that the more correct, safest way is to do something like:

Code: Pascal  [Select]
  1. procedure TForm1.onEv(Sender: TObject);
  2. var
  3.   NewObject: TMyClass;
  4. begin
  5.   if Sender.InheritsFrom(TMyClass) then begin
  6.     NewObject := TMyClass(Sender);
  7.     {... etc ...}
  8.   end;
  9. end;
or
Code: Pascal  [Select]
  1. procedure TForm1.onEv(Sender: TObject);
  2. var
  3.   NewObject: TMyClass;
  4. begin
  5.   if Sender is TMyClass then begin
  6.     NewObject := TMyClass(Sender);
  7.     {... etc ...}
  8.   end;
  9. end;
or, if you don't mind the ocassional error:
Code: Pascal  [Select]
  1. procedure TForm1.onEv(Sender: TObject);
  2. var
  3.   NewObject: TMyClass;
  4. begin
  5.   NewObject := Sender as TMyClass;
  6.   {... etc ...}
  7. end;
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.6/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

xenon54

  • Newbie
  • Posts: 4
Re: Inherit event procedure
« Reply #6 on: February 25, 2020, 10:26:58 pm »
Very little. Basically you save up one line. But note that the more correct, safest way is to do something like:

Code: Pascal  [Select]
  1. procedure TForm1.onEv(Sender: TObject);
  2. var
  3.   NewObject: TMyClass;
  4. begin
  5.   if Sender.InheritsFrom(TMyClass) then begin
  6.     NewObject := TMyClass(Sender);
  7.     {... etc ...}
  8.   end;
  9. end;
or
Code: Pascal  [Select]
  1. procedure TForm1.onEv(Sender: TObject);
  2. var
  3.   NewObject: TMyClass;
  4. begin
  5.   if Sender is TMyClass then begin
  6.     NewObject := TMyClass(Sender);
  7.     {... etc ...}
  8.   end;
  9. end;
or, if you don't mind the ocassional error:
Code: Pascal  [Select]
  1. procedure TForm1.onEv(Sender: TObject);
  2. var
  3.   NewObject: TMyClass;
  4. begin
  5.   NewObject := Sender as TMyClass;
  6.   {... etc ...}
  7. end;

Thx for reply. In my case, i totally know that my class is inherits from sender.

I just search way to override param class.

PascalDragon

  • Hero Member
  • *****
  • Posts: 1092
  • Compiler Developer
Re: Inherit event procedure
« Reply #7 on: February 26, 2020, 09:21:28 am »
I just search way to override param class.

You simply can't. If the event is declared as procedure(Sender: TObject) of object, then you must give it a method declared as procedure BlaBla(Sender: TObject). And if it's declared as procedure(Socket: TLSocket) of object, then you must use a method declared as procedure BlaBla(Socket: TLSocket). If you want something else then you have to cast (be it with a hard cast or an absolute).