Recent

Author Topic: Override not working  (Read 13097 times)

eurythmic

  • New Member
  • *
  • Posts: 36
Override not working
« on: June 23, 2015, 01:27:27 pm »
Me again... With hopefully my last question for a while! I have written the following parent class:

Code: [Select]
type
  Temployee=class
    protected
      employeeID:integer;
      employeename:string;
      dateofbirth:string;
      jobtitle:string;
    public
      constructor create(i:integer;n,d,t:string); virtual;
      function getemployeeID:integer;
      function getemployeename:string;
      function getdateofbirth:string;
      function getjobtitle:string;
      procedure setemployeename(n:string);
      procedure setjobtitle(t:string);
      procedure viewdetails; virtual;
  end;

I have declared as virtual the methods I need to be able to override in sub-classes.

Here is my sub-class:

Code: [Select]
type ptemployee = class(temployee)
  private
    hoursworked:integer;
  public
    constructor create(i,h:integer; n,d,t:string); override;
    procedure viewdetails; override;
end; 

When I run this I get the following error: "there is no method in an ancestor class to be overridden"

It works if I use "reintroduce" rather than "override", but this isn't a long-term solution as if I have a list of employees I want it to still use methods of the sub-class where the list contains objects of the sub-class.

Can anyone help?

Thanks,

Sophie

eurythmic

  • New Member
  • *
  • Posts: 36
Re: Override not working
« Reply #1 on: June 23, 2015, 01:30:12 pm »
Oh, it seems that overriding isn't necessary for constructors... Am I correct?

Blaazen

  • Hero Member
  • *****
  • Posts: 3241
  • POKE 54296,15
    • Eye-Candy Controls
Re: Override not working
« Reply #2 on: June 23, 2015, 01:42:37 pm »
Your constructors have different parameters:
Code: [Select]
constructor create(i:integer;n,d,t:string); virtual;
and
Code: [Select]
constructor create(i,h:integer; n,d,t:string); override;
In this case virtual and override will not work but you can still call
Code: [Select]
inherited Create(); with the correct parameters (constructor of ancestor).
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

eurythmic

  • New Member
  • *
  • Posts: 36
Re: Override not working
« Reply #3 on: June 23, 2015, 01:48:11 pm »
I've got my program working by just removing the word "override" from the ptemployee constructor. Is there any reason why this wouldn't be ok?

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Override not working
« Reply #4 on: June 23, 2015, 01:48:48 pm »
Oh, it seems that overriding isn't necessary for constructors... Am I correct?
No thats incorrect.
Please provide a simplified example of what is not working. Something compilable preferably. The portions of code you shown, except the fact that you try to add one extra parameter to an overridden constructor, does not seam to have any other problems.

You can not add extra parameters when you override a method you have to use the existing the same parameters in number, type and order, the reintroduce keyword must be used for that no way around keep in mind that reintroduce will only silence the compiler's complains about hiding an existing method assuming that you know what you are doing. Thats it if you have a class variable of TEmployee set to ptemployee and call its constructor it will not know about the reintroduced constructor and will call the one declared in the temployee class.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

eurythmic

  • New Member
  • *
  • Posts: 36
Re: Override not working
« Reply #5 on: June 23, 2015, 02:26:18 pm »
Here's my code, which is working since I removed "override" from the construtor and I'm intrigued to know whether there's anything wrong with doing this.

(I know it's not a great program, it's just a simple little one for me whilst I try to get my head around this)

Main program:

Code: [Select]
program employeemanager;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes, employee, parttime
  { you can add units after this };

var
  choice:char;

procedure addfull;
var
  id:integer;
  name,date,title:string;
  added:temployee;
begin
    writeln('Enter employee ID');
    readln(ID);
    writeln('Enter employee name');
    readln(name);
    writeln('Enter their DOB');
    readln(date);
    writeln('Enter their job title');
    readln(title);
    added:=temployee.create(ID, name, date, title);
    writeln('Here is what you added: ');
    added.viewdetails;
    readln;
end;

procedure addpart;
var
  id,hours:integer;
  name,date,title:string;
  added:ptemployee;
begin
  writeln('Enter employee ID');
  readln(ID);
  writeln('Enter employee name');
  readln(name);
  writeln('Enter their DOB');
  readln(date);
  writeln('Enter their job title');
  readln(title);
  writeln('How many hours do they work per week?');
  readln(hours);
  added:=ptemployee.create(ID, hours, name, date, title);
  writeln('Here is what you added: ');
  added.viewdetails;
  readln;
end;

begin
  writeln('which would you like to add?');
  writeln('P. part-time employee');
  writeln('F. full-time employee');
  readln(choice);
  case choice of
       'P': addpart;
       'F': addfull;
  end;
end.                       

Employee unit:

Code: [Select]
unit employee;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils;

type
  Temployee=class
    protected
      employeeID:integer;
      employeename:string;
      dateofbirth:string;
      jobtitle:string;
    public
      constructor create(i:integer;n,d,t:string); virtual;
      function getemployeeID:integer;
      function getemployeename:string;
      function getdateofbirth:string;
      function getjobtitle:string;
      procedure setemployeename(n:string);
      procedure setjobtitle(t:string);
      procedure viewdetails; virtual;
  end;

implementation

constructor TEmployee.create(i:integer;n,d,t:string);
begin
  employeeID:=i;
  employeename:=n;
  dateofbirth:=d;
  jobtitle:=t;
end;

function TEmployee.getemployeeID:integer;
begin
  getemployeeID:=employeeID;
end;

function TEmployee.getemployeename:string;
begin
  getemployeename:=employeename;
end;

function TEmployee.getdateofbirth:string;
begin
  getdateofbirth:=dateofbirth;
end;

function TEmployee.getjobtitle:string;
begin
  getjobtitle:=jobtitle;
end;

procedure TEmployee.setemployeename(n:string);
begin
  employeename:=n;
end;

procedure TEmployee.setjobtitle(t:string);
begin
  jobtitle:=t;
end;

procedure TEmployee.viewdetails;
begin
  writeln('Employee ID: ',employeeID);
  writeln('Employee name: ',employeename);
  writeln('Employee date of birth: ',dateofbirth);
  writeln('Employee job title: ',jobtitle);
end;

end.                                     

Part-time employee unit (sub-class):

Code: [Select]
unit parttime;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, employee;

type ptemployee = class(temployee)
  private
    hoursworked:integer;
  public
    constructor create(i,h:integer; n,d,t:string);
    procedure viewdetails; override;
end;

implementation

constructor ptemployee.create(i,h:integer; n,d,t:string);
begin
  employeeID:=i;
  hoursworked:=h;
  employeename:=n;
  dateofbirth:=d;
  jobtitle:=t;
end;

procedure ptemployee.viewdetails;
begin
  writeln('Employee ID: ',employeeID);
  writeln('Employee name: ',employeename);
  writeln('Employee date of birth: ',dateofbirth);
  writeln('Employee job title: ',jobtitle);
  writeln('Hours worked per week: ',hoursworked);
end;

end.
                                 

typo

  • Hero Member
  • *****
  • Posts: 3051
Re: Override not working
« Reply #6 on: June 23, 2015, 02:41:10 pm »
The compiler message happens because your new constructor does not have the same parameters as the prior one. So it is a new constructor.

eurythmic

  • New Member
  • *
  • Posts: 36
Re: Override not working
« Reply #7 on: June 23, 2015, 02:47:50 pm »
Yep, we've got there thanks - see above - so my question now is, is there a problem with just having a new constructor for objects of the sub-class? The program as I've posted it above now seems to work with no problems.

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: Override not working
« Reply #8 on: June 23, 2015, 03:02:29 pm »
You can inherit them too, calling from the parent class:
Code: [Select]
constructor ptemployee.create(i,h:integer; n,d,t:string);
begin
  inherited Create(i, n, d, t);
  hoursworked:=h;
end;

This guarantees that you don't rewrite same code over and over and do mistakes that way.

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Override not working
« Reply #9 on: June 23, 2015, 03:28:51 pm »
1) Calling the inherited constructor is mandatory not optional.
2) if you are not using class variables then don't waste time on virtual override reintroduce.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

eurythmic

  • New Member
  • *
  • Posts: 36
Re: Override not working
« Reply #10 on: June 23, 2015, 03:40:46 pm »
Afraid I don't understand either of your points, taazz!

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Override not working
« Reply #11 on: June 23, 2015, 03:50:01 pm »
1)
Code: [Select]
constructor ptemployee.create(i,h:integer; n,d,t:string);
begin
  inherited create..... //<- this one is not optional it must always be called.
  employeeID:=i;
  hoursworked:=h;
  employeename:=n;
  dateofbirth:=d;
  jobtitle:=t;
end;
2)
Code: [Select]
type
  TEmployeeClass = class of TEmployee.

function GetNextEmploye(aClass:TEmployeeClass):TEmployee;
begin
  Result := aclass.create(i, 'n','d','t');
end;
aClass is a class variable not an object variable. GetNextEmploye returns an object create from the class passed in aClass. If you do not use class variables then don't waste your time with override, reintroduce, virtual. constructors. If you only use the class directly then what ever the constructor is declared the compiler has all the info required. While when using the class variable the details need to be known at runtime and not using virtual or using reintroduce breaks the detail info chain.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

eurythmic

  • New Member
  • *
  • Posts: 36
Re: Override not working
« Reply #12 on: June 23, 2015, 04:22:42 pm »
Quote
If you do not use class variables then don't waste your time with override, reintroduce, virtual. constructors.

I'm teaching A Level Computing - this stuff is on the syllabus, so I have to teach it.

In my example, I have tried removing all references to virtual and override and yes, the program still seems to work. However in the exam the students would be expected to include virtual and override. I guess it gets them into good habits for later, or something...

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Override not working
« Reply #13 on: June 23, 2015, 04:39:39 pm »
Quote
If you do not use class variables then don't waste your time with override, reintroduce, virtual. constructors.

I'm teaching A Level Computing - this stuff is on the syllabus, so I have to teach it.

In my example, I have tried removing all references to virtual and override and yes, the program still seems to work. However in the exam the students would be expected to include virtual and override. I guess it gets them into good habits for later, or something...
Designing a class hierarchy based on virtual constrains is a must learn. It teaches 2 basic skills 1) minimization of required parameters (less is more) 2) creation of hard to break hierarchy chains. When I say break I mean to find something you can't do with the existing hierarchy. In my perspective adding parameters in the constructor to initialize the internal fields is the wrong design. Try using something more relevant eg employer id or something not allowed to change through properties after the creation.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4676
  • I like bugs.
Re: Override not working
« Reply #14 on: June 23, 2015, 04:56:55 pm »
I'm teaching A Level Computing - this stuff is on the syllabus, so I have to teach it.
In my example, I have tried removing all references to virtual and override and yes, the program still seems to work. However in the exam the students would be expected to include virtual and override. I guess it gets them into good habits for later, or something...

You will teach virtual functions without understanding what they are? Uhhh. You really must learn the fundamental ideas behind this feature! It implements polymorphism which is an essential part of object oriented programming.

It is good I am not attending your class. In school I wanted to understand everything and asked dummy questions from teachers. You would have hard times with me!
A good teacher knows his topic thoroughly and can answer questions also outside of his teaching material.
Mostly Lazarus trunk and FPC 3.2 on Manjaro Linux 64-bit.

 

TinyPortal © 2005-2018