Sign in Join

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

Mailing lists / fpc-pascal / 2017-09

implements

14 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

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

Ryan Joseph

I think I asked this some years ago but I came across it again I just don’t get what the point of this is. There is an “implements” property but it seems like yet another half-baked feature from Delphi that wasn’t implemented completely or is broken. What’s the point of implementing an interface like this on TBaseClass if you need to access all the methods by using the property name (“hook” in this case) when you could just add an instance of THook in TBaseClass? It adds so much noise and clutter in the language and for what? The only reason it makes sense is if you could call “base.DoIt” and omit the .hook every time you’re typing but that was overlooked for some reason. Why??

type
  IHook = interface ['IHook']
    procedure DoIt;
  end;
type
	THook = class (IHook)
		procedure DoIt;
	end;
procedure THook.DoIt;
begin
	writeln(ClassName+' did it');
end;
type
	TBaseClass = class (IHook)
		private
			m_hook: IHook;
		public
			property Hook: IHook read m_hook implements IHook;
			constructor Create;
	end;
constructor TBaseClass.Create;
begin
	m_hook := THook.Create;
end;
base: TBaseClass;
base := TBaseClass.Create;
base.DoIt; // CANT DO THIS
base.hook.DoIt; // MUST DO THIS

Regards,
Ryan Joseph

Sven Barth
"Ryan Joseph" wrote
I think I asked this some years ago but I came across it again I just

don’t get what the point of this is. There is an “implements” property but it seems like yet another half-baked feature from Delphi that wasn’t implemented completely or is broken. What’s the point of implementing an interface like this on TBaseClass if you need to access all the methods by using the property name (“hook” in this case) when you could just add an instance of THook in TBaseClass? It adds so much noise and clutter in the language and for what? The only reason it makes sense is if you could call “base.DoIt” and omit the .hook every time you’re typing but that was overlooked for some reason. Why??

Show quoted text 38 lines
type IHook = interface ['IHook'] procedure DoIt; end; type THook = class (IHook) procedure DoIt; end; procedure THook.DoIt; begin writeln(ClassName+' did it'); end; type TBaseClass = class (IHook) private m_hook: IHook; public property Hook: IHook read m_hook implements IHook; constructor Create; end; constructor TBaseClass.Create; begin m_hook := THook.Create; end; base: TBaseClass; base := TBaseClass.Create; base.DoIt; // CANT DO THIS base.hook.DoIt; // MUST DO THIS

Because you must use the interface and not the class instance:

=== code begin ===

var
  base: TBaseClass;
  hook: IHook;
begin
  base := TBaseClass.Create;
  hook := base;
  hook.DoIt; // will call base.hook.DoIt
end;

=== code end ===

Regards,
Sven

Ryan Joseph
to Sven Barth
Show quoted text 18 lines
On Sep 2, 2017, at 2:35 PM, Sven Barth via fpc-pascal wrote: Because you must use the interface and not the class instance: === code begin === var base: TBaseClass; hook: IHook; begin base := TBaseClass.Create; hook := base; hook.DoIt; // will call base.hook.DoIt end; === code end ===

but then what is the purpose of this? It was almost a very powerful way to add methods to a class without subclassing (like class helpers) but the simple fact the “hook” identifier is not implied makes it useless. The only possible use of this I could think of is not needing to type “hook.” every time but since you need to anyways I just don’t get it.

Regards,
Ryan Joseph

Graeme Geldenhuys
to Ryan Joseph
Ryan Joseph wrote
but then what is the purpose of this?

Please search the internet about Interfaces and probably Design Patterns too. Have ever heard the phrase: "Code to an Interface, not an Implementation".

Interfaces are so much more than simply "adding methods to a class".

Regards,
Graeme

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp
Ryan Joseph
to Graeme Geldenhuys
Show quoted text 5 lines
On Sep 2, 2017, at 3:27 PM, Graeme Geldenhuys wrote: Please search the internet about Interfaces and probably Design Patterns too. Have ever heard the phrase: "Code to an Interface, not an Implementation". Interfaces are so much more than simply "adding methods to a class".

I understand interfaces just fine but I don’t understand why you want a class to appear as if it implements an interface but then having to call methods on a 2nd class. It separates the code (which is nice) but then gives you an annoying extra step of typing hook.XXX for every method. It just feels broken and not complete as a feature.

Furthermore if you know that a class implements an interface but you need to call another variable (like hook) then how do you know the name of the variable??? I use interfaces often but that would break them for me in most cases.

Regards,
Ryan Joseph

Graeme Geldenhuys
to Ryan Joseph
Ryan Joseph wrote
It separates the code (which is nice) but then gives you an annoying extra step of typing hook.XXX for every method.

I don't have that problem, and I use interfaces extensively. Like multi-threading, Interfaces are an advanced feature of the Object Pascal language. Unfortunately, many ways that it can be used incorrectly too.

When I use interfaces, I work with the object instance only via an Interface reference. The interface that represents the functionality I need. I also prefer not to use reference counting with interface, but I definitely see a use for reference counting - but again, never mix the two in the same application. I also use interface delegation, which reduces code a lot.

Probably the best example I can think of off the top of my head that shows Interface usage very well is a set of 8 articles (with code) implementing Model-View-Presenter (MVP). I don't know where I originally code the articles and code from, but I can email you [in private] what I have. She shows prenty of ways using interfaces.

Regards,
Graeme

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp
Sven Barth
to Ryan Joseph: I understand interfaces just fine but I don’t understand why you want a class to appear…
"Ryan Joseph" wrote 6 lines
> On Sep 2, 2017, at 3:27 PM, Graeme Geldenhuys < wrote: > > Please search the internet about Interfaces and probably Design

Patterns too. Have ever heard the phrase: "Code to an Interface, not an Implementation".

> > Interfaces are so much more than simply "adding methods to a class". I understand interfaces just fine but I don’t understand why you want a

class to appear as if it implements an interface but then having to call methods on a 2nd class. It separates the code (which is nice) but then gives you an annoying extra step of typing hook.XXX for every method. It just feels broken and not complete as a feature.

Furthermore if you know that a class implements an interface but you need

to call another variable (like hook) then how do you know the name of the variable??? I use interfaces often but that would break them for me in most cases.

As Graeme said: the point is to code against interfaces, not classes. Don't pass around or work with the TBaseClass instance, instead only with the IHook interface. And this is what the implements feature is for.

Regards,
Sven

Michael Schnell
to Graeme Geldenhuys: I don't have that problem, and I use interfaces extensively. Like multi-threading,…
Graeme Geldenhuys wrote
Like multi-threading, Interfaces are an advanced feature of the Object Pascal language. Unfortunately, many ways that it can be used incorrectly too.

Unfortunately multi-threading is not a feature of the Object Pascal language :( . Oxygen does have it ("parallel loop" and "future"). I do hope some day this will be seen in fpc (based on a thread-pool implemented in the rtl).

Re Interfaces: Do you know a decent description of how to use Interface _as_a_language_feature_ (e.g. in fpc) completely independent of their use with certain OS-provided libraries ?

I once saw an implementation of a high bit count calculation library based in Interfaces to add reference counting to the objects used to hold the values. Do you suggest this Is a "correct use" of interfaces ?

-Michael

Ryan Joseph
to Sven Barth: Patterns too. Have ever heard the phrase: "Code to an Interface, not an Implementation".…
Show quoted text 5 lines
On Sep 2, 2017, at 6:56 PM, Sven Barth via fpc-pascal wrote: As Graeme said: the point is to code against interfaces, not classes. Don't pass around or work with the TBaseClass instance, instead only with the IHook interface. And this is what the implements feature is for.

Sorry I forgot about this.

So I learned that Supports() returns the correct interface (IHook in my example) and THAT I can see is helpful now because the implementation of the interface can be shared across many classes. That’s what I was looking for in terms of a practical use patterns for “implements properties”. I should have seen that at the start but I’m still hung up on how it’s implemented.

Regards,
Ryan Joseph

Ryan Joseph
to Michael Schnell: Unfortunately multi-threading is not a feature of the Object Pascal language :( . Oxygen…
On Sep 4, 2017, at 3:45 PM, Michael Schnell wrote: Re Interfaces: Do you know a decent description of how to use Interface _as_a_language_feature_ (e.g. in fpc) completely independent of their use with certain OS-provided libraries ?

As an alternate to polymorphism but without subclassing. That’s why I wanted the “implements” feature to implicitly include the name of the property so they would behave like this transparently.

Regards,
Ryan Joseph

Graeme Geldenhuys
to Ryan Joseph: Sorry I forgot about this. So I learned that Supports() returns the correct interface…
Ryan Joseph wrote
That’s what I was looking for in terms of a practical use patterns for “implements properties”. I should have seen that at the start but I’m still hung up on how it’s implemented.

And to come back to your example in your first post:

  // your code
  TBaseClass = class (IHook)
  private
    m_hook: IHook;
  public
    constructor Create;
    property Hook: IHook read m_hook implements IHook;
  end;

What I do, and I suggest you try it too. Because you are using interfaces, the idea is that you use the Interface Reference variable only, never the property. To help you with that, move the "Hook" property from the Public section of the class, to the Private section.

  // with my changes
  TBaseClass = class (IHook)
  private
    m_hook: IHook;
    property Hook: IHook read m_hook implements IHook;
  public
    constructor Create;
  end;

There is NO need to make Hook public, because you can always get access to that functionality via the Supports() call and get a reference to IHook.

Regards,
Graeme

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp
Ryan Joseph
to Graeme Geldenhuys
On Sep 6, 2017, at 2:50 PM, Graeme Geldenhuys wrote: There is NO need to make Hook public, because you can always get access to that functionality via the Supports() call and get a reference to IHook.

The Supports() call is the key takeaway here.

For the sake of discussion can you see why it makes sense that “hook.” syntax would be implied because the class does indeed supposedly implement the interface? Everything about the syntax says that the methods in IHook should be in TBaseClass so I can’t help but feel like it was an omission or not fully finished. It would be messy to implement probably because you would risk a number of name collisions with existing methods.

Regards,
Ryan Joseph

Sven Barth
to Ryan Joseph
"Ryan Joseph" wrote 6 lines
> On Sep 6, 2017, at 2:50 PM, Graeme Geldenhuys < wrote: > > There is NO need to make Hook public, because you can always get access

to that functionality via the Supports() call and get a reference to IHook.

The Supports() call is the key takeaway here. For the sake of discussion can you see why it makes sense that “hook.”

syntax would be implied because the class does indeed supposedly implement the interface? Everything about the syntax says that the methods in IHook should be in TBaseClass so I can’t help but feel like it was an omission or not fully finished. It would be messy to implement probably because you would risk a number of name collisions with existing methods.

No it's definitely by design. If you use alias clauses ("procedure IMyIntf.Foobar = Blubb") then you also won't have the interface's method in your class, but only the alias. The method can only be accesssed by the interface's method name by using an interface instance not the class instance. The "implements" clause is just an advanced variant of that in that it allows you to use a complete class (though you're still able to implement selected methods of the interface in the base class which aren't delegated then).

Regards,
Sven

Graeme Geldenhuys
to Ryan Joseph: The Supports() call is the key takeaway here. For the sake of discussion can you see why…
Ryan Joseph wrote
For the sake of discussion can you see why it makes sense that “hook.” syntax would be implied because the class does indeed supposedly implement the interface? Everything about the syntax says that the methods in IHook should be in TBaseClass so I can’t help but feel like it was an omission or not fully finished.

"implements" in that example says that the implementation of the IHook interface is delegated to another class - THook. If you didn't define the property... implements in TBaseClass, then TBaseClass would have had to explicitly implement all methods of IHook. The implements means you can reuse the IHook implementation (thanks to THook) in many other classes too.

Granted I personally don't like the syntax for "implements", but that's what Borland came up with for Delphi, and FPC follows that syntax for compatibility reasons.

The other annoying thing of Object Pascal's Interface support is that you need to specify which interfaces you implement, even in descendant classes where the parent already implements a specific interface. But that's a whole other discussion. ;-)

Regards,
Graeme

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp