简体   繁体   中英

Delphi: how to access an object's base class methods from an interface type variable

...or vice versa. Let's suppose two classes on which I have no control, both inherit from the same base class:

TDataSet1 = class(TDataSet)
...
end;

TDataSet2 = class(TDataSet)
...
end;

I have an interface declaration like this:

IMyDataSet = interface
  procedure MyProc;
end;

Then I have two classes that inherit from the previous ones and that implement my interface:

TMyDataSet1 = class(TDataSet1, IMyDataSet)
  procedure MyProc;
end;

TMyDataSet2 = class(TDataSet2, IMyDataSet)
  procedure MyProc;
end;

Now my problem is: i have a bunch of procedures and functions which must accept as parameter an object which can be an instance of both my classes. I don't need to access properties or methods specific to my two classes or to the ancestor ones, only those from the base class TDataSet and those declared in the interface IMyDataSet .

If I declare a procedure like this:

procedure Foo(ADataSet: TDataSet);

I can only call methods from TDataSet class.

If instead I declare the procedure in this way:

procedure Foo(ADataSet: IMyDataSet);

I can see only methods that belong to that interface.

Is there a way so that I can see both TDataSet and IMyDataSet methods on the reference I pass to the procedure?

You can declare parameter as interface and then typecast it to object reference inside method. (This kind of typecasting works in Delphi 2010 and newer)

procedure Foo(ADataSet: IMyDataSet);
var
  LDataSet: TDataSet;
begin
  LDataSet := TDataSet(ADataSet);
  ... 
end;

Note: If IMyDataSet interface is not implemented on TDataSet class above typecast will fail without raising exception and return nil .

You can also use as operator to typecast, but in that case failure raises exception.

LDataSet := ADataSet as TDataSet;

Another option is to pass parameter as object instance and then retrieve interface from object. In that case your interface must have GUID.

IMyDataSet = interface
  ['{XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}'] // replace with actual GUID
  procedure MyProc;
end;

procedure Foo(ADataSet: TDataSet);
var
  LDataSet: IMyDataSet;
begin
  if Supports(ADataSet, IMyDataSet, LDataSet) then
    begin
      ... 
    end;
end;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM