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