How do you override delegated method implementation?

In Delphi 2007, I use one class to implement one of the supported interfaces of the second class. It works. Help Delphi reports:

By default, using the keyword delegate implements the entire interface of the methods. However, you can use method resolution clauses or declare methods in your class that implement some of the interface methods to override this default behavior.

However, when I declare a method in my second class that has the corresponding signature of one of the interface methods, it does not receive the call.

Interestingly, this is because I access the class through another interface when I create it.

The following is a test program demonstrating my problem:

program Project1; {$APPTYPE CONSOLE} type IInterface1 = interface ['{15400E71-A39B-4503-BE58-B6D19409CF90}'] procedure AProc; end; IInterface2 = interface ['{1E41CDBF-3C80-4E3E-8F27-CB18718E8FA3}'] end; TDelegate = class(TObject) protected procedure AProc; end; TMyClass = class(TInterfacedObject, IInterface1, IInterface2) strict private FDelegate: TDelegate; property Delegate: TDelegate read FDelegate implements IInterface1; public constructor Create; destructor Destroy; override; procedure AProc; end; procedure TDelegate.AProc; begin writeln('TClassDelegate.AProc'); end; constructor TMyClass.Create; begin inherited; FDelegate := TDelegate.Create; end; destructor TMyClass.Destroy; begin FDelegate.Free; inherited; end; procedure TMyClass.AProc; begin writeln('TMyClass.AProc'); end; var MyObj : IInterface2; begin MyObj := TMyClass.Create; (MyObj as IInterface1).AProc; end. 

When I run this, I get the output:

TClassDelegate.AProc

I want to:

TMyClass.AProc

Any help was appreciated.

+4
source share
4 answers

It seems you need to reuse your method as follows:

 TMyClass = class(TInterfacedObject, IInterface1, IInterface2) strict private .... procedure test(); public .... procedure IInterface1.AProc = test; end; procedure TMyClass.test; begin writeln('TMyClass.AProc'); end; 

therefore IInterface1.AProc for TMyClass mapped to Test() (not to FDelegate.AProc ) and the result is TMyClass.AProc

+5
source

Perhaps this is due to the visibility of the property. Every time I use implements , protected or public properties, the same goes for all the examples that I could find in VCL (e.g. TAutoObjectEvent .

Attempt # 2:

What happens if you remove the AProc() method from TMyClass ? Does he use one on TDelegate ?

+1
source

Part of the documentation mentioned seems outdated. If you try to use method permission for the interface that is used in the implements clause, you will get compiler error E2264: cannot have method permission for interface '% s " .

The solution shown in the link above - just giving the procedure the same name as declared in the interface also does not work in Delphi XE (it compiles, but the procedure is not called).

+1
source

The documentation explicitly states that the behavior you see is constructed like this:

If the delegate property is of a class type, this class and its ancestors look for methods that implement the specified interface before exploring the surrounding class and its ancestors.

I assume that in the full example, you have an interface with several methods and you want the majority to be defined by the delegate, and specific, overridden by the implementation class. I don’t see how to achieve this with only one class, but this can be done by introducing a second class:

 program Project1; {$APPTYPE CONSOLE} type IInterface1 = interface ['{15400E71-A39B-4503-BE58-B6D19409CF90}'] procedure AProc; procedure AnotherProc; end; TDelegate = class protected procedure AProc; procedure AnotherProc; end; TMyClass = class(TInterfacedObject, IInterface1) strict private FDelegate: TDelegate; property Delegate: TDelegate read FDelegate implements IInterface1; public constructor Create; destructor Destroy; override; procedure AProc; end; TMyOtherClass = class(TMyClass, IInterface1) procedure IInterface1.AProc = AProc; end; procedure TDelegate.AProc; begin writeln('TDelegate.AProc'); end; procedure TDelegate.AnotherProc; begin writeln('TDelegate.AnotherProc'); end; constructor TMyClass.Create; begin inherited; FDelegate := TDelegate.Create; end; destructor TMyClass.Destroy; begin FDelegate.Free; inherited; end; procedure TMyClass.AProc; begin writeln('TMyClass.AProc'); end; var MyObj: IInterface1; begin MyObj := TMyOtherClass.Create; MyObj.AProc; MyObj.AnotherProc; Readln; end. 

As @teran points out, if you are ready to rename your method, then there is a simpler solution.

+1
source

Source: https://habr.com/ru/post/1399304/


All Articles