I have problem with implementing relation between some classes. I got three different classes serving three different forms. All these classes speak in same language, so they are inherited from same class called TAncestorServer
. Let’s call its descendants TForm1Server
, TForm2Server
, and TForm3Server
. TAncestorServer
contains an abstract method called Function1
, so TForm1
, TForm2
, and TForm3
can call it with no problem through their own classes inherited from it, they have an access to the classes through a property named Server
. But the problem is about another form called TForm4
! It’s very similar to other forms but it’s not independent like them. It works with TForm2Server
or TForm3Server
. Still not a problem, but imagine another method like Function2
which is declared in TForm2Server
and TForm3Server
, TForm4
needs to call them. I can go like this:
if Server is TForm2Server then
TForm2Server(Server).Function2
else if Server is TForm3Server then
TForm3Server(Server).Function2;
But it can turn in an infinite if-else clause! So I thought something like multiple-inheritance may help here. I declared an interface called IForm4Server
which contains Function2
. So TForm2Server
and TForm3Server
inherit from both TAncestorServer
and IForm4Server
. I thought something like this could work:
If Server is IForm4Server then
IForm4Server(Server).Function2;
But compiler doesn’t think so, it says that it’s not a valid type cast, because TAncestorServer
is not IForm4Server
, which is absolutely right. TForm1Server
has no idea about implementing Function2
and has to leave it blank. I can’t declare TForm4.Server
as IForm4Server
too, because Function1
represents a huge number of methods and properties, however I still can’t type cast IForm4Server
to TAncestorServer
.
As a solution I can define two different properties in TForm4
like GeneralServer: TAncestorServer
and Form4Server: IForm4Server
and then assign same instance of TForm2Server
or TForm3Server
to them, but I don’t feel good about it. How should I do this? Is there any standard pattern for it?
Interfaces can inherit from one or more interfaces. The derived interface inherits the members from its base interfaces. A class that implements a derived interface must implement all members in the derived interface, including all members of the derived interface's base interfaces.
When a class implements the inherited interface then it must provide the implementation of all the members that are defined within the interface inheritance chain.
But unlike classes, interfaces can actually inherit from multiple interfaces. This is done by listing the names of all interfaces to inherit from, separated by comma. A class implementing an interface which inherits from multiple interfaces must implement all methods from the interface and its parent interfaces.
The interface keyword is used to declare a special type of class that only contains abstract methods. To access the interface methods, the interface must be "implemented" (kinda like inherited) by another class with the implements keyword (instead of extends ).
Implementing one or many interfaces is the correct approach, but looks like you're a bit confused about the proper syntax and have no experience with interfaces.
Basic things are:
I made the most simple example I can think off, using visual inheritance for forms and a simple interface. The extracts of the example follows:
type
TServerForm = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
procedure Method1; virtual;
end;
type
IMyInterface = interface
['{B7102C7E-F7F6-492A-982A-4C55CB1065B7}']
procedure Method2;
end;
This one inherits from the TServerForm and implements the interface
type
TServerForm3 = class(TServerForm, IMyInterface)
public
procedure Method1; override;
procedure Method2;
end;
This one just inherits from TServerForm
type
TServerForm4 = class(TServerForm)
public
procedure Method1; override;
end;
and this one inherits directly from TForm and implements the interface
type
TNoServerForm = class(TForm, IMyInterface)
public
procedure Method2;
end;
All the forms are auto-created and then, I have this code to call the methods on a couple of OnClick
for buttons on another form (the main form of the application example):
To call the virtual method based on polymorphism:
procedure TForm6.Button1Click(Sender: TObject);
var
I: Integer;
begin
for I := 0 to Screen.FormCount - 1 do
begin
if (Screen.Forms[I] is TServerForm) then
TServerForm(Screen.Forms[I]).Method1;
end;
end;
To call the method based on the implementation of the interface:
procedure TForm6.Button2Click(Sender: TObject);
var
I: Integer;
Intf: IMyInterface;
begin
for I := 0 to Screen.FormCount - 1 do
begin
if Supports(Screen.Forms[I], IMyInterface, Intf) then
Intf.Method2;
end;
end;
The methods just show messages, and everything works fine:
procedure TServerForm3.Method2;
begin
ShowMessage(ClassName + '.Method2');
end;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With