Compiler not understand "inherited;" lazarus / 64-FPC development ---------------------------------------------------------------------- ASerge · 2019-02-21 15:17 Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program Project1; {$MODE OBJFPC}{$H+} uses Interfaces, StdCtrls, LMessages; type  TTest = class(TComboBox)    procedure CNCommand(var TheMessage: TLMCommand); message CN_COMMAND; // Copied from TCustomComboBox declaration  end; procedure TTest.CNCommand(var TheMessage: TLMCommand);begin  //inherited CNCommand(TheMessage); // project1.lpr(14,13) Error: Identifier idents no member "CNCommand"  //inherited; // project1.lpr(15,12) Error: Wrong number of parameters specified for call to "CNCommand"               // customcombobox.inc(1078,27) Error: Found declaration: CNCommand(var TLMCommand);end; beginend.Uncomment to see errors. Tested on FPC 3.0.4 and FPC 3.1.1 in Windows. If change to unrealized method-message, than it understands. For example, change to CNCommand + 1. I can understand the first error - calling an inherited method from the private section. For the second error - not. In Delphi such code does not generate a compiler error. ---------------------------------------------------------------------- rvk · 2019-02-21 15:52 Quote from: ASerge on February 21, 2019, 04:17:41 pmIn Delphi such code does not generate a compiler error. Then use {$MODE DELPHI} ---------------------------------------------------------------------- ASerge · 2019-02-21 17:06 Quote from: rvk on February 21, 2019, 04:52:45 pmThen use {$MODE DELPHI}  Yeah, then it'll work. But it's still weird. As then in mode OBJFPC override methods messages? They are usually defined in the private section. And usually the parent handler is called. OBJFPC mode does not allow this scenario. ---------------------------------------------------------------------- Zoran · 2019-02-21 20:37 Quote from: ASerge on February 21, 2019, 06:06:16 pmQuote from: rvk on February 21, 2019, 04:52:45 pmThen use {$MODE DELPHI}  Yeah, then it'll work. But it's still weird. As then in mode OBJFPC override methods messages? They are usually defined in the private section. And usually the parent handler is called. OBJFPC mode does not allow this scenario. You are right. I tried to find this difference in documentation, but without success. Please report it, this should at least be documented. I don't think that this can be changed by modeswitches, so you cannot do anything except using delphi mode. As a workaround, you might create an intermediate class in separate unit, which only overrides the needed message method in protected block. For example: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit UnitTestExposeMessage; {$mode delphi} interface uses  StdCtrls, LMessages; type  TComboBoxExposeMessage = class(TComboBox)  protected    procedure CNCommand(var TheMessage: TLMCommand); message CN_COMMAND;  end; implementation procedure TComboBoxExposeMessage.CNCommand(var TheMessage: TLMCommand);begin  //inherited CNCommand(TheMessage); // This still does not compile.  inherited; // But this compiles.end; end.  Only this intermediate unit has to be compiled in delphi mode, and then derive your class from this intermediate class: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit UnitTest; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, StdCtrls, UnitTestExposeMessage, LMessages; type  TTest = class(TComboBoxExposeMessage)  private    // ...  protected    procedure CNCommand(var TheMessage: TLMCommand); message CN_COMMAND;   // ...  public   // ...  end; implementation procedure TTest.CNCommand(var TheMessage: TLMCommand);begin  inherited CNCommand(TheMessage);  // more code...end; end. ---------------------------------------------------------------------- lucamar · 2019-02-21 21:54 I'm not sure of this (never tested it) but I think that to be able to call inherited, the method must be virtual in the parent class and you must override it in the child; otherwise the child's method just hides the parent's However, this can't be done with message methods, if I'm reading the documentation properly, because they are somehow "special". Or maybe they can? Can you try this?: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program Project1; {$MODE OBJFPC}{$H+} uses Interfaces, StdCtrls, LMessages; type  TTest = class(TComboBox)    procedure CNCommand(var TheMessage: TLMCommand); override; {message CN_COMMAND;}  end; procedure TTest.CNCommand(var TheMessage: TLMCommand);begin  inherited CNCommand(TheMessage); { Or just:  inherited;  }end; beginend. Since message methods are also virtual, it may work ---------------------------------------------------------------------- rvk · 2019-02-21 22:18 Quote from: lucamar on February 21, 2019, 10:54:21 pmI'm not sure of this (never tested it) but I think that to be able to call inherited, the method must be virtual in the parent class and you must override it in the child; otherwise the child's method just hides the parent's Actually, the inherited call is a special one where there does not need to be virtual/override. Also see note #2 here https://castle- engine.io/modern_pascal_introduction.html#_calling_inherited_method QuoteBut the inherited keyword works regardless if the method is virtual or not. The inherited always means that the compiler starts searching for the method in an ancestor, and it makes sense for both virtual and not virtual methods. The problem is that CNCommand is private in the ancestor so it can't be reached (in objfpc-mode). ---------------------------------------------------------------------- Zoran · 2019-02-21 22:18 Quote from: lucamar on February 21, 2019, 10:54:21 pm Since message methods are also virtual, it may work As you can see in ASerge's and my posts, it does not work in objfpc mode -- when the message method is private in parent class you cannot use inherited. However, in delphi mode you can (but only without the method name). This difference between modes doesn't seem to be documented. However, it was probably made so intentionally -- for Delphi compatibility. If I remember well (I don't have Delphi any more), in VCL components message methods are almost always declared in private section, but this doesn't prevent overriding them in derived classes, this is allowed in Delphi. In LCL however, these methods are usually declared in published protected section (but not always, not in this case). Edit: corrected lapsus - protected instead of published