Hello together!
I have taken the time to implement a first version of Delphi's class helpers. Thanks to Jonas' code for Objective C categories it was a rather easy to get that working.
I have yet to test the compatibility of this implementation with Delphi and this is where the FPC community comes in. I'd like you (@all list readers) - if possible - to test this extension with tasks you'd use them in and also to test what behaves differently from Delphi if you have a current Delphi version available (I believe you need Delphi 2007 or newer for this).
Especially at the core devs, but maybe also for other interested persons I have the following questions regarding the implementation of this feature:
- should class helpers have access to protected fields of the extended class? I propose not or this would beat the complete idea of "sealed" (I also believe that Delphi doesn't allow it as well)
- should class helpers be able to be instantiated or even referenced in any way? (including forward declarations)
- should class helpers be allowed to override/reintroduce methods?
- should class helpers be able to extend other class helpers (as class helpers are implemented as child classes of the extended class this might currently be possible)?
- should class helpers be able to implement interfaces?
- can/should "message" methods be forbidden?
- should abstract methods be forbidden?
- should a class helper for class X hide a method which was introduced in a subclass of X?
- can class helpers extend generic classes?
- can class helpers BE generic?
I have attached the patch which implements the class helper syntax in the trunk compiler. Please note that this might not be the final version, so please do not rely on the syntax and especially the behavior.
Class helpers adhere to the following syntax (I'm still thinking whether I should slap Borland/Codegear for that...)
type
[ClassName] = class helper for [ExtendedClass]
class procedure SomeClassMethod;
procedure SomeMethod;
(...)
end;The methods are implemented like in a normal class, but "Self" refers to an instance of the extended class in normal methods and to the class itself if used inside a class method (of course other methods implemented by the class helper are available as well... basically a class helper is a child class of the extended class).
The methods implemented by class helpers are automatically available if the class helper is available in the current scope. The methods are called as if they belong to the extended class:
var
c: [ExtendedClass];
begin
// class methods
[ExtendedClass].SomeClassMethod;
c := [ExtendedClass].Create;
c.SomeClassMethod;
c.SomeMethod;
end;For the case you are still looking for a usecase: On the Lazarus mailing list was posted such one by ugaciaka in this mail: http://lists.lazarus.freepascal.org/pipermail/lazarus/2010-December/058368.html A possible answer for his first question would be the following (untested and maybe also properties would work...):
type
TCheckListBoxHelper = class helper for TCheckListBox
function GetCheckedCount: Integer;
end;
function TCheckListBoxHelper.GetCheckedCount: Integer;
var
i: Integer;
begin
Result := 0;
// Count and Checked belong to the extended TCheckListBox
for i := 0 to Count - 1 do
if Checked[i] then
Inc(Result);
end;
(...)
// somewhere in a piece of code that has access to a TCheckListBox instance
c := SomeCheckListBox.GetCheckedCount;Please feel free to comment, criticise, test and discuss this feature and more especially its implementation.
Regards,
Sven
