Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2015-07

question with interfaces, hooks

8 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

David Emerson

Hi list!

I'm just starting in with interfaces, and am happy to see there is something similar to multiple inheritence available. But it seems to be limited in a way I will show below, so I am wondering if there is something I am missing. Example code says it best...

program test_interfaces;
{$mode objfpc}{$H+}
uses classes, sysutils;
type
   i_foo = interface
     procedure foo;
   end;
   t_foo_base = class (TInterfacedObject, i_foo)
     procedure foo;
   end;
   t_fancy_class_base = class
     // the idea is that I can't reasonably rebase this on t_foo_base
     procedure bar;
   end;
   t_fancy_class = class (t_fancy_class_base, i_foo)
     private
       f_hook : i_foo;
     public
       constructor create; // instantiates f_hook as a t_foo_base
       destructor destroy; override; // destroys the above
       property hook : i_foo read f_hook implements i_foo;
   end;
procedure t_foo_base.foo;
   begin
     writeln ('foo');
   end;
procedure t_fancy_class_base.bar;
   begin
     writeln ('bar');
   end;
constructor t_fancy_class.create;
   begin
     inherited;
     f_hook := t_foo_base.create;
   end;
destructor t_fancy_class.destroy;
   begin
     t_foo_base(f_hook).free;
     inherited;
   end;
var
   fc : t_fancy_class;
   foo : i_foo;
begin
   fc  := t_fancy_class.create;
   foo := t_fancy_class.create;
   fc.foo;          // this won't compile-- why?
   i_foo(fc).foo;   // this works, but is cumbersome
   foo.bar;                // this understandably won't compile
   t_fancy_class(foo).bar; // we can do this if needed
end.

So... since t_fancy_class implements the interface i_foo, why is t_fancy_class.foo not available? foo is also generally unavailable from within methods of t_fancy_class, an equal frustration.

Is there some mode switch or some such I can use to make it generally available?

Thanks!

~David

Reply by email

Sven Barth
to David Emerson

Am 15.07.2015 06:07 schrieb "David Emerson" :
[snip]

Show quoted text 11 lines
constructor t_fancy_class.create; begin inherited; f_hook := t_foo_base.create; end; destructor t_fancy_class.destroy; begin t_foo_base(f_hook).free; inherited; end;

[snip]

Not related to your problem, but important nevertheless: you don't need to free interface variables. They are reference counted an freed automatically at least if you don't mix a class reference (in your case to t_foo_base) and interface reference (in your case i_foo) which you shouldn't do anyway (and which you aren't doing in your example).

I haven't work with delegation much, but you could try to do "(fc as i_foo).foo;". Also you might want to take a ,
Sven

Reply by email

Sven Barth
to Graeme Geldenhuys

Am 15.07.2015 09:27 schrieb "Graeme Geldenhuys" <

Show quoted text 10 lines
: On 2015-07-15 05:06, David Emerson wrote: > So... since t_fancy_class implements the interface i_foo, why is > t_fancy_class.foo not available? Because you told it a property named "hook" implements it, so you need to call it as follows: fc.hook.foo;

"implements" should avoid the need for this. It merely tells the compiler to look for methods using that property. The property could even be protected or private and it should still work as long as the containing class has the interface in its parent list.

Regards,
Sven

Reply by email

Graeme Geldenhuys
to Sven Barth
Sven Barth wrote
The property could even be protected or private and it should still work as long as the containing class has the interface in its parent list.

I thought that would only work if you access the method via an interface variable, not a class instance variable.

In his sample code fc is a class instance.

I didn't test if his sample code works under Delphi though. Then again, if I work with Interfaces, I only ever use an interface reference to call methods of that interface.

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/

Reply by email

Sven Barth
to Graeme Geldenhuys

Am 15.07.2015 11:51 schrieb "Graeme Geldenhuys" <

Show quoted text 15 lines
: On 2015-07-15 10:21, Sven Barth wrote: > The property could even be > protected or private and it should still work as long as the containing > class has the interface in its parent list. I thought that would only work if you access the method via an interface variable, not a class instance variable. In his sample code fc is a class instance. I didn't test if his sample code works under Delphi though. Then again, if I work with Interfaces, I only ever use an interface reference to call methods of that interface.

Ehm yes, as a class instance variable it probably only works using the property. I'd need to test this in Delphi as well however ;)

Regards,
Sven

Reply by email

David Emerson
to Sven Barth: [snip] [snip] Not related to your problem, but important nevertheless: you don't need to…

Thanks, Graeme and Sven!

Sven Barth wrote 5 lines
Not related to your problem, but important nevertheless: you don't need to free interface variables. They are reference counted and freed automatically at least if you don't mix a class reference (in your case to t_foo_base) and interface reference (in your case i_foo) which you shouldn't do anyway (and which you aren't doing in your example).

Hmm, I just followed the example here:
http://wiki.lazarus.freepascal.org/How_To_Use_Interfaces In that example I guess the TRealClass.Destroy is unnecessary?

I also do not understand what you mean by mixing a class reference and an interface reference; hopefully I will not do that.

I haven't work with delegation much, but you could try to do "(fc as i_foo).foo;". Also you might want to take a seen in the example, i_foo(fc).foo works, which seems more or less

equivalent to (fc as i_foo).foo.

I'm looking at TAggregatedObject, and getting deeper into this, wondering what the real purposes are of these features. I have been wanting multiple inheretance, and using a "hook...implements" is the closest thing available. But there seems to be more to it than that. Is there any recommended reading on the subject of interfaces, delegation, etc? Any example code that shows the power of interfaces or TAggregatedObject in a somewhat useful example?

Thanks,
David

Reply by email

Graeme Geldenhuys
to David Emerson
David Emerson wrote
Any example code that shows the power of interfaces or TAggregatedObject in a somewhat useful example?

The best Interfaces usage I've ever seen was done by Joanna Carter with her MVP implementation. The articles and source code is available on my server. I've learned a ton from that code.

http://geldenhuys.co.uk/~graemeg/Joanna_Carter_MVP/

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/

Reply by email