Recent

Author Topic: Classes - Inheritance - how to add an additional parameter to the constructor?  (Read 3575 times)

rwebb616

  • Full Member
  • ***
  • Posts: 133
Here is what I have currently:

Code: Pascal  [Select][+][-]
  1. unit headsup.classes.word;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils;
  9.  
  10. type
  11.  
  12.   { TWord }
  13.  
  14.   TWord = class
  15.  
  16.   private
  17.     FCategory : string;
  18.     FWord : string;
  19.     FPlayed : boolean;
  20.  
  21.   public
  22.     constructor Create (Category : String; Word : string; Played : boolean);
  23.     property Word: String Read FWord Write FWord;
  24.     property Category : String Read FCategory Write FCategory;
  25.     property Played : Boolean Read FPlayed Write FPlayed;
  26.  
  27.   end;
  28.  
  29.   { TPlayedWord }
  30.  
  31.   TPlayedWord = class(Tword)
  32.  
  33.     constructor Create (Category : String; Word : String; Played : boolean; Correct : boolean); override;
  34.  
  35.     private
  36.       FCorrect:boolean;
  37.     public
  38.       property Correct : Boolean Read FCorrect Write FCorrect;
  39.  
  40.  
  41.   end;
  42.  
  43. implementation
  44.  
  45. { TPlayedWord }
  46.  
  47. constructor TPlayedWord.Create(Correct: boolean);
  48. begin
  49.   inherited;
  50.   FPlayed := Played;
  51.   FCategory := Category;
  52.   FWord := Word;
  53.   FCorrect := Correct;
  54. end;
  55.  
  56. { TWord }
  57.  
  58. constructor TWord.Create(Category: String; Word: string; Played : boolean);
  59. begin
  60.   FPlayed := Played;
  61.   FCategory := Category;
  62.   FWord := Word;
  63.  
  64. end;
  65.  
  66. end.
  67.  

What am I doing wrong?  TPlayedword is inheriting from Tword and I want to be able to pass one additional parameter to TPlayedword - the "Correct" boolean.

Compiler is complaining about Duplicate identifier but when I remove the three original ones it gives me a different error "There is no method in ancestor class to be overridden constructor create(boolean);

Rich

cdbc

  • Hero Member
  • *****
  • Posts: 995
    • http://www.cdbc.dk
Hi
Overload the constructor
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE5 -> FPC 3.2.2 -> Lazarus 2.2.6 up until Jan 2024 from then on it's: KDE5/QT5 -> FPC 3.3.1 -> Lazarus 3.0

zamronypj

  • Full Member
  • ***
  • Posts: 133
    • Fano Framework, Free Pascal web application framework
Here is what I have currently:

Code: Pascal  [Select][+][-]
  1. unit headsup.classes.word;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils;
  9.  
  10. type
  11.  
  12.   { TWord }
  13.  
  14.   TWord = class
  15.  
  16.   private
  17.     FCategory : string;
  18.     FWord : string;
  19.     FPlayed : boolean;
  20.  
  21.   public
  22.     constructor Create (Category : String; Word : string; Played : boolean);
  23.     property Word: String Read FWord Write FWord;
  24.     property Category : String Read FCategory Write FCategory;
  25.     property Played : Boolean Read FPlayed Write FPlayed;
  26.  
  27.   end;
  28.  
  29.   { TPlayedWord }
  30.  
  31.   TPlayedWord = class(Tword)
  32.  
  33.     constructor Create (Category : String; Word : String; Played : boolean; Correct : boolean); override;
  34.  
  35.     private
  36.       FCorrect:boolean;
  37.     public
  38.       property Correct : Boolean Read FCorrect Write FCorrect;
  39.  
  40.  
  41.   end;
  42.  
  43. implementation
  44.  
  45. { TPlayedWord }
  46.  
  47. constructor TPlayedWord.Create(Correct: boolean);
  48. begin
  49.   inherited;
  50.   FPlayed := Played;
  51.   FCategory := Category;
  52.   FWord := Word;
  53.   FCorrect := Correct;
  54. end;
  55.  
  56. { TWord }
  57.  
  58. constructor TWord.Create(Category: String; Word: string; Played : boolean);
  59. begin
  60.   FPlayed := Played;
  61.   FCategory := Category;
  62.   FWord := Word;
  63.  
  64. end;
  65.  
  66. end.
  67.  

What am I doing wrong?  TPlayedword is inheriting from Tword and I want to be able to pass one additional parameter to TPlayedword - the "Correct" boolean.

Compiler is complaining about Duplicate identifier but when I remove the three original ones it gives me a different error "There is no method in ancestor class to be overridden constructor create(boolean);

Rich

duplicate error because you use parameter name  Category, Word, Played while you have property with same name. Rename parameter to different names such as aCategory etc. Override is not needed as parent method is not same in signature and not marked as virtual
Code: [Select]
constructor Create (aCategory : String; aWord : String; aPlayed : boolean; aCorrect : boolean);

Code: [Select]
constructor TPlayedWord.Create (aCategory : String; aWord : String; aPlayed : boolean; aCorrect : boolean);
begin
      inherited create(aCategory, aWord, aPlayed);
      fCorrect := aCorrect;
end;

Also using word as property name is not recommended as pascal has type with name word.
« Last Edit: May 07, 2021, 02:24:46 am by zamronypj »
Fano Framework, Free Pascal web application framework https://fanoframework.github.io
Apache module executes Pascal program like scripting language https://zamronypj.github.io/mod_pascal/
Github https://github.com/zamronypj

zamronypj

  • Full Member
  • ***
  • Posts: 133
    • Fano Framework, Free Pascal web application framework
"WORD" is a reserved word. It is a Type that is 2 bytes wide..

Use something else in its place. Like AGameWord or something.

 At least don't try do make a variable := WORD;

incorrect. word is not reserved word but type definition
https://www.freepascal.org/docs-html/ref/refse3.html
Fano Framework, Free Pascal web application framework https://fanoframework.github.io
Apache module executes Pascal program like scripting language https://zamronypj.github.io/mod_pascal/
Github https://github.com/zamronypj

egsuh

  • Hero Member
  • *****
  • Posts: 1266
You should add virtual to TWord.Create to override it.

rwebb616

  • Full Member
  • ***
  • Posts: 133
I have this now and it seems to work:

Code: Pascal  [Select][+][-]
  1. unit headsup.classes.word;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils;
  9.  
  10. type
  11.  
  12.   { TWord }
  13.  
  14.   TWord = class
  15.  
  16.   private
  17.     FCategory : string;
  18.     FWord : string;
  19.     FPlayed : boolean;
  20.  
  21.   public
  22.     constructor Create (aCategory : String; aWord : string; aPlayed : boolean);
  23.     property Word: String Read FWord Write FWord;
  24.     property Category : String Read FCategory Write FCategory;
  25.     property Played : Boolean Read FPlayed Write FPlayed;
  26.  
  27.   end;
  28.  
  29.   { TPlayedWord }
  30.  
  31.   TPlayedWord = class(Tword)
  32.  
  33.     constructor Create (aCategory: String; aWord: string; aPlayed : boolean; aCorrect: boolean);
  34.  
  35.     private
  36.       FCorrect:boolean;
  37.     public
  38.       property Correct : Boolean Read FCorrect Write FCorrect;
  39.  
  40.  
  41.   end;
  42.  
  43. implementation
  44.  
  45. { TPlayedWord }
  46.  
  47. constructor TPlayedWord.Create(aCategory: String; aWord: string; aPlayed : boolean; aCorrect: boolean);
  48. begin
  49.   FPlayed := aPlayed;
  50.   FCategory := aCategory;
  51.   FWord := aWord;
  52.   FCorrect := aCorrect;
  53. end;
  54.  
  55. { TWord }
  56.  
  57. constructor TWord.Create(aCategory: String; aWord: string; aPlayed : boolean);
  58. begin
  59.   FPlayed := aPlayed;
  60.   FCategory := aCategory;
  61.   FWord := aWord;
  62.  
  63. end;
  64.  
  65. end.
  66.  

I don't know if it's good practice or not.  By the way I've been wondering what the 'a' signifies in the declaration of the procedures?  I know 'F' usually means Field. 

rwebb616

  • Full Member
  • ***
  • Posts: 133
duplicate error because you use parameter name  Category, Word, Played while you have property with same name. Rename parameter to different names such as aCategory etc. Override is not needed as parent method is not same in signature and not marked as virtual
Code: [Select]
constructor Create (aCategory : String; aWord : String; aPlayed : boolean; aCorrect : boolean);

Code: [Select]
constructor TPlayedWord.Create (aCategory : String; aWord : String; aPlayed : boolean; aCorrect : boolean);
begin
      inherited create(aCategory, aWord, aPlayed);
      fCorrect := aCorrect;
end;

Also using word as property name is not recommended as pascal has type with name word.

This is what seemed to resolve it - I named them as you did and it compiled.  I will change Word at some point.. just didn't feel like searching through my whole codebase to find where I'm using it and change it.

(I know the IDE can probably do this quickly)
Rich

egsuh

  • Hero Member
  • *****
  • Posts: 1266
Quote
I've been wondering what the 'a' signifies in the declaration of the procedures?
It doesn't mean anything special. Just to escape using the same identifier --- you have declared Category, Word, etc. as property name within the class. Parameter names have significance only within the procedure/function, so it's relatively unimportant how to name them.

howardpc

  • Hero Member
  • *****
  • Posts: 4144
  By the way I've been wondering what the 'a' signifies in the declaration of the procedures?
A consistently applied naming convention can improve readability of code, and go some way to save you from making simple errors.
An obvious "convention" you can apply is to avoid using the same identifier to refer to different variables (with the exception of trivial examples such as say i for an integer loop variable). The objfpc mode enforces this in some situations. While some coders find this unnecessarily restrictive, personally I like tramlines that keep you away from potential ambiguity and confusion.
Prefixing parameter names with "a" (if done consistently) gives an immediate visual cue that this is not a locally declared or global variable, but a parameter. In short programs this makes little difference.

However, when you write code with thousands of lines, conventions such as this can really help in deciphering code that uses literally hundreds of variables and parameters. Thinking "count" is a global variable or public property when in the current scope it is actually a parameter of your current hundred-line function (whose header has scrolled out of view) leads to immediate grief. Making a visual distinction between them at the declaration stage avoids that potential confusion.
« Last Edit: May 07, 2021, 05:58:19 am by howardpc »

rwebb616

  • Full Member
  • ***
  • Posts: 133
I understand the reasoning - just didn't know if there was a particular meaning for 'A'..  as people prefix class fields with 'F' for Field.  Didn't know if there was a similar nomenclature for 'A' or 'a' other than it's just conveniently the first letter of the alphabet! :)


lucamar

  • Hero Member
  • *****
  • Posts: 4219
By the way I've been wondering what the 'a' signifies in the declaration of the procedures?  I know 'F' usually means Field.

Besides what Howard wrote, the origin of the "A" prefix convention was to mean the generic English "a" ("one") as in "a category", "a string", "a whatever", etc. That's why sometimes you'll see e.g. "AnObject" or "AnInteger". Though, through internacionalization, it has almost lost that original "meaning".

But no, it's not because "it is the first letter of the alphabet" ;D
« Last Edit: May 07, 2021, 06:03:52 am by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

rwebb616

  • Full Member
  • ***
  • Posts: 133

Besides what Howard wrote, the origin of the "A" prefix convention was to mean the generic English "a" ("one") as in "a category", "a string", "a whatever", etc. That's why sometimes you'll see e.g. "AnObject: TObject". Though, through internacionalization, it has almost lost that original "meaning".

Ahh.. I wondered if that was it because, yes I had seen both AnObject and AObject before in example code.


PascalDragon

  • Hero Member
  • *****
  • Posts: 5444
  • Compiler Developer
I understand the reasoning - just didn't know if there was a particular meaning for 'A'..  as people prefix class fields with 'F' for Field.  Didn't know if there was a similar nomenclature for 'A' or 'a' other than it's just conveniently the first letter of the alphabet! :)

The 'A' or 'a' prefix stands for 'argument' (aka 'parameter' due to 'P' already being used for pointers).

Bart

  • Hero Member
  • *****
  • Posts: 5265
    • Bart en Mariska's Webstek
The 'A' or 'a' prefix stands for 'argument' (aka 'parameter' due to 'P' already being used for pointers).

I always imagined that the A just was that: a, as in AString meaning "a string", which more or less equals "some string".

Another dream just shattered ...

Bart

lucamar

  • Hero Member
  • *****
  • Posts: 4219
The 'A' or 'a' prefix stands for 'argument' (aka 'parameter' due to 'P' already being used for pointers).
I always imagined that the A just was that: a, as in AString meaning "a string", which more or less equals "some string"..

Yeah, I though so too (more so when you find code that instead uses "the", as in "TheString") but after the Dragon's answer I am starting to think that it really means (or meant) nothing and that any interpretation is purely subjective ;)
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

 

TinyPortal © 2005-2018