Q: BEST PRACTICES
Q: BEST PRACTICES
I have a question regarding best practices in defining a method as abstract in a parent/ancestor class, that is called from said parent/ancestor, but only implemented in descendant classes.
Below is an example that details my question further. Basically, I'm not sure if this method is considered "best practices" and I wondered if there was a more preferred method...
// ** 2014-09-11 10:30am GMT-8
// ** Reworked the code with the advice, moved the ancestor virtual/abstract method to "protected" and added "override" in the GetValue() method declared in the descendant.
// ** As a result, it doesn't look like I need to "cast" or pass a "sender/self" variable.
// ** I've never heard of "SOLID", I'll look into it.
unit TEST_classinheritance2_main;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TClass1 = class
protected
function GetValue() : integer; virtual; abstract;
public
procedure AMethod();
end;
TClass2 = class(TClass1)
private
function GetValue() : integer; override;
public
end;
{$REGION 'Form'}
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
{$ENDREGION}
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TClass1.AMethod();
begin
// * ABSTRACT ERROR
// *
// * The following line will ONLY generate an EAbstractError,
// * if the "override" keyword is not used in the declaration of the
// * method in the descendant class
try
// * ABSTRACT ERROR IN THIS LINE UNLESS "OVERRIDE" is USED
showMessage(format('GetValue():[%d]', [self.GetValue()]));
except
on E:Exception do
showMessage(E.Message);
end;
end;
function TClass2.GetValue() : integer;
begin
result := 2;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
AClass2 : TClass2;
begin
AClass2 := TClass2.Create();
try
AClass2.AMethod();
finally
AClass2.Free();
end;
end;
end.
I have a question regarding best practices in defining a method as abstract in a parent/ancestor class, that is called from said parent/ancestor, but only implemented in descendant classes.
Below is an example that details my question further. Basically, I'm not sure if this method is considered "best practices" and I wondered if there was a more preferred method...
// ** 2014-09-11 10:30am GMT-8
// ** Reworked the code with the advice, moved the ancestor virtual/abstract method to "protected" and added "override" in the GetValue() method declared in the descendant.
// ** As a result, it doesn't look like I need to "cast" or pass a "sender/self" variable.
// ** I've never heard of "SOLID", I'll look into it.
unit TEST_classinheritance2_main;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TClass1 = class
protected
function GetValue() : integer; virtual; abstract;
public
procedure AMethod();
end;
TClass2 = class(TClass1)
private
function GetValue() : integer; override;
public
end;
{$REGION 'Form'}
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
{$ENDREGION}
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TClass1.AMethod();
begin
// * ABSTRACT ERROR
// *
// * The following line will ONLY generate an EAbstractError,
// * if the "override" keyword is not used in the declaration of the
// * method in the descendant class
try
// * ABSTRACT ERROR IN THIS LINE UNLESS "OVERRIDE" is USED
showMessage(format('GetValue():[%d]', [self.GetValue()]));
except
on E:Exception do
showMessage(E.Message);
end;
end;
function TClass2.GetValue() : integer;
begin
result := 2;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
AClass2 : TClass2;
begin
AClass2 := TClass2.Create();
try
AClass2.AMethod();
finally
AClass2.Free();
end;
end;
end.
The compiler probably will give you a message about a lower visibility of the overridden method. So that also should be protected. And also congratulations, you just discovered the polymorphism achievement :)
ReplyDeleteMany thanks. Sure glad that I went through this exercise by making simplified code. It was ugly trying to figure this out with a big project. Thanks again guys.
ReplyDelete[DCC Hint] TEST_classinheritance2_main.pas(20): H2269 Overriding virtual method 'TClass2.GetValue' has lower visibility (private) than base class 'TClass1' (protected)
Sure enough. Moved GetValue() to protected as well in the descendant.
+1 to Polymorphic Abilities