Sign in Join

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

Mailing lists / fpc-pascal / 2018-04

Multiple active class helpers at same time

18 messages · 7 people · –

Reply by email Subscribe to this list Your subscription

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

LacaK

Hi ,

I am sure that this was already discussed, but I can not find any conclusion.

Is planned support for multiple class(objet, record) helpers in a way, that all class helpers can be used in parallel not only one?

My use case is:

In unit A I have declared base class.
In unit B I have declared helper for class defined in unit A which adds some extended functionality (new methods) to class A In unit C I have declared helper for class defined in unit A which adds some extended functionality (new methods) to class A

In program P1 once I need only functionality defined in A, B so I use A,B In program P2 I need functionality defined in A,B,C so I want use A,B,C but It does not work as only one class helper can be active.

If such feature will not be implemented, is there any other way how to solve this problem (how to add functionalities to one class by adding more units to final program)?
If such featurn can be implemented is there already feature request in bug tracker?

Thanks

-Laco.

Maciej Izak
to LacaK

2018-04-23 13:26 GMT+02:00 LacaK :

If such feature will not be implemented, is there any other way how to solve this problem (how to add functionalities to one class by adding more units to final program)?

This can be easily solved by "default field" feature. The work is in progress (not yet in trunk), but can be tested with NewPascal version of FPC compiler. You can check examples (compilable with NewPascal):

https://github.com/maciej-izak/PascalSmartPointers/tree/master/examples

the usage in PascalSmartPointers is rather more advanced and related to management operators, but please note that "default field" can easily replace type helpers/record helpers/class helpers and "default field" is able to work even with dynamic arrays.

Best regards, Maciej Izak
LacaK
to Maciej Izak

Dňa 23.4.2018 o 13:52 Maciej Izak napísal(a):

Show quoted text 13 lines

Thank you.
Can you give small example for my use case ? I can not understand from above mentioned examples.

So I need to have:

unit A;
type
   TClassA = class
     public
        procedure Method1;
   end;
unit B;
type
   TClassAHelper1 = class helper for TClassA
     public
       procedure MethodB1;
       procedure MethodB2;
end;
unit C;
type
   TClassAHelper2 = class helper for TClassA
     public
       procedure MethodC1;
       procedure MethodC2;
end;

and in program:

use A,B,C;
var instanceA: TClassA;
...
instanceA := TClassA.Create;
instanceA.Method1;
instanceA.MethodB1; // defined in unit B
instanceA.MethodC1; // defined in unit C
...

L.

Sven Barth
to LacaK: I am sure that this was already discussed, but I can not find any conclusion. Is planned…

LacaK schrieb am Mo., 23. Apr. 2018, 13:34:

Show quoted text 8 lines
Hi , I am sure that this was already discussed, but I can not find any conclusion. Is planned support for multiple class(objet, record) helpers in a way, that all class helpers can be used in parallel not only one?

Yes, it is planned. Main problem currently (aside from time) is to define when a method hides the method of another helper, especially when inheritance (both for the helper and the extended type) is involved.

Regards,
Sven

Maciej Izak
to LacaK: Dňa 23.4.2018 o 13:52 Maciej Izak napísal(a): Thank you. Can you give small example for…

2018-04-23 14:02 GMT+02:00 LacaK :

Can you give small example for my use case ? I can not understand from above mentioned examples.
unit A;
type
  TClassA = class
  public
    procedure Method1;
  end;
unit B;
type
  TClassAHelper1<T> = record
  private
    instance: T default;
  public
    procedure MethodB1;
    procedure MethodB2;
  end;
unit C;
type
  TClassAHelper2<T> = record
  private
    instance: T default;
  public
    procedure MethodC1;
    procedure MethodC2;
  end;

and in program:

use A,B,C;
var instanceA: TClassAHelper1<TClassAHelper2<TClassA>>; // it can be
composed in other way (more elegant for example as specialization in new
type)
...
instanceA := TClassA.Create;
instanceA.Method1;
instanceA.MethodB1; // defined in unit B
instanceA.MethodC1; // defined in unit C
Best regards, Maciej Izak
Mattias Gaertner
to Sven Barth: LacaK schrieb am Mo., 23. Apr. 2018, 13:34: Yes, it is planned. Main problem currently…
Show quoted text 14 lines
LacaK schrieb am Mo., 23. Apr. 2018, 13:34: > Hi , > > I am sure that this was already discussed, but I can not find any > conclusion. > > Is planned support for multiple class(objet, record) helpers in a way, > that all class helpers can be used in parallel not only one? > Yes, it is planned. Main problem currently (aside from time) is to define when a method hides the method of another helper, especially when inheritance (both for the helper and the extended type) is involved.

How will this be activated?
A modeswitch?
Will it be default enabled in mode objfpc and disabled in mode delphi?

Mattias

Maciej Izak
to Mattias Gaertner

2018-04-23 14:21 GMT+02:00 Mattias Gaertner :

How will this be activated? A modeswitch? Will it be default enabled in mode objfpc and disabled in mode delphi?

There was discussion about this while ago... and there was a lot of problems.

IMO the best option to solve all problems, is expansion in "aspects" functionality. I have some experiments with modified helpers for types (as aspects for classes), and what I can say now :

full potential of class/record/type helpers is not used :), and by bad choice can be loses for ever. IMO The best direction for type helpers (which can solve all problems) is usage "with" for example:

var
  x: TObjectA with THelper1, THelper2;

AFAIK should be possible to create new sub kind of helpers : aspects with new syntax and functionalities. IIRC Sven did not want to use "with" just for "type helpers" because it is reserved for more amazing feature like "aspects", but when type helper has the same root as aspect (aspect as sub kind of helper) then "with" can be used for both : "type helpers" and "type aspects"

Best regards, Maciej Izak
Marco van de Voort
to Maciej Izak

In our previous episode, Maciej Izak said:

Show quoted text 14 lines
full potential of class/record/type helpers is not used :), and by bad choice can be loses for ever. IMO The best direction for type helpers (which can solve all problems) is usage "with" for example: var x: TObjectA with THelper1, THelper2; AFAIK should be possible to create new sub kind of helpers : aspects with new syntax and functionalities. IIRC Sven did not want to use "with" just for "type helpers" because it is reserved for more amazing feature like "aspects", but when type helper has the same root as aspect (aspect as sub kind of helper) then "with" can be used for both : "type helpers" and "type aspects"

IMHO having to change every reference/declaration kind of the defeats the purpose of helpers a bit.

Michael Van Canneyt
to Marco van de Voort
Marco van de Voort wrote 18 lines
In our previous episode, Maciej Izak said: > > full potential of class/record/type helpers is not used :), and by bad > choice can be loses for ever. IMO The best direction for type helpers > (which can solve all problems) is usage "with" for example: > > var > x: TObjectA with THelper1, THelper2; > > AFAIK should be possible to create new sub kind of helpers : aspects with > new syntax and functionalities. IIRC Sven did not want to use "with" just > for "type helpers" because it is reserved for more amazing feature like > "aspects", but when type helper has the same root as aspect (aspect as sub > kind of helper) then "with" can be used for both : "type helpers" and "type > aspects" IMHO having to change every reference/declaration kind of the defeats the purpose of helpers a bit.

True if you don't want to use a local variable, but I think the idea has merit in the sense that you can be very explicit about what type helpers you want in case of doubt. If it is an optional syntax, I don't see why not.

Michael.

LacaK
to Sven Barth: LacaK schrieb am Mo., 23. Apr. 2018, 13:34: Yes, it is planned. Main problem currently…
Show quoted text 9 lines
Is planned support for multiple class(objet, record) helpers in a way, that all class helpers can be used in parallel not only one? Yes, it is planned. Main problem currently (aside from time) is to define when a method hides the method of another helper, especially when inheritance (both for the helper and the extended type) is involved.

Later in uses clause wins ... as for other cases where in different units are used same names
But probably problem is deeper , what I am not aware of ;-) -Laco.

Ryan Joseph
to Sven Barth: LacaK schrieb am Mo., 23. Apr. 2018, 13:34: Yes, it is planned. Main problem currently…
On Apr 23, 2018, at 7:13 PM, Sven Barth via fpc-pascal wrote: Yes, it is planned. Main problem currently (aside from time) is to define when a method hides the method of another helper, especially when inheritance (both for the helper and the extended type) is involved.

Probably the best feature of Objective-C (and now Swift) is categories/extensions which are basically class helpers but with no limits on scope like in FPC. I never had problems with naming conflicts and I use them very often to split up large classes and extend library classes. Maybe looking at how “extensions” are implemented in Swift is a good idea? (https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Extensions.html)

Btw why in the world did Delphi limit the scope like they did? It’s such a sad shortcoming of a great feature that everyone loves who works in the aforementioned languages. In fact I barely ever use them in FPC because I know if I rely on them too much I could get trapped in a situation where I have a scope conflict and there’s nothing I can do!

Regards,
Ryan Joseph

Ryan Joseph
to LacaK: Later in uses clause wins ... as for other cases where in different units are used same…
On Apr 23, 2018, at 8:22 PM, LacaK wrote: Later in uses clause wins ... as for other cases where in different units are used same names But probably problem is deeper , what I am not aware of ;-)

Swift just gives a compiler error if there is a redefinition of method in the current scope. Very simple and works just fine. Why not do what Swift/Objective-C does given this is a proven implementation? At least as a starting point if nothing else.

extension MyObject {
func foo() {

}
}

extension MyObject {
func foo() { // redefinition error

}
}

Regards,
Ryan Joseph

Sven Barth
to LacaK: Later in uses clause wins ... as for other cases where in different units are used same…

LacaK schrieb am Mo., 23. Apr. 2018, 15:22:

Show quoted text 16 lines
> Is planned support for multiple class(objet, record) helpers in a way, > that all class helpers can be used in parallel not only one? > Yes, it is planned. Main problem currently (aside from time) is to define when a method hides the method of another helper, especially when inheritance (both for the helper and the extended type) is involved. Later in uses clause wins ... as for other cases where in different units are used same names But probably problem is deeper , what I am not aware of ;-) -Laco.

As I said the problem arises when inheritance enters the field as the rules are a bit different there.

Regards,
Sven

Ryan Joseph
to Sven Barth
On Apr 24, 2018, at 12:57 AM, Sven Barth via fpc-pascal wrote: As I said the problem arises when inheritance enters the field as the rules are a bit different there.

Why should helper methods be allowed to redefine existing methods anyways? As I mentioned Swift/ObjC don’t even allow this and just use a simple compiler error when a redefinition occurs. If that’s what’s holding up the feature I would say just go with Swift/ObjC’s implementation which is already proven in the real world to work.

Regards,
Ryan Joseph

Sven Barth
to Ryan Joseph

Ryan Joseph schrieb am Di., 24. Apr. 2018,
04:03:

Show quoted text 15 lines
> On Apr 24, 2018, at 12:57 AM, Sven Barth via fpc-pascal < > wrote: > > As I said the problem arises when inheritance enters the field as the rules are a bit different there. > Why should helper methods be allowed to redefine existing methods anyways? As I mentioned Swift/ObjC don’t even allow this and just use a simple compiler error when a redefinition occurs. If that’s what’s holding up the feature I would say just go with Swift/ObjC’s implementation which is already proven in the real world to work.

Because that is how helper currently work. Extending it with a new feature will not change that.

Regards,
Sven

Ryan Joseph
to Sven Barth
On Apr 24, 2018, at 12:48 PM, Sven Barth via fpc-pascal wrote: Because that is how helper currently work. Extending it with a new feature will not change that.

I made an example to see how this would look. What’s the problem with “last in wins” like seen below? Seems pretty straightforward to me.

type
	TClassA = class
		procedure DoThis; virtual;
	end;
type
	TClassB = class (TClassA)
		procedure DoThis; override;
	end;
type
	TClassHelper_A1 = class helper for TClassA
		procedure DoThis; // overloads TClassA.DoThis
	end;
type
	TClassHelper_A2 = class helper for TClassA
		procedure DoThis; // overloads TClassHelper_A1.DoThis
	end;
type
	TClassHelper_B1 = class helper for TClassB
		procedure DoThis; // overloads TClassB.DoThis
	end;
var
	classA: TClassA;
	classB: TClassB;
begin
	classA.DoThis; // calls TClassHelper_A2.DoThis
	classB.DoThis; // calls TClassHelper_B1.DoThis

Regards,
Ryan Joseph

Sven Barth
to Ryan Joseph

Ryan Joseph schrieb am Di., 24. Apr. 2018,
10:44:

Show quoted text 12 lines
> On Apr 24, 2018, at 12:48 PM, Sven Barth via fpc-pascal < > wrote: > > Because that is how helper currently work. Extending it with a new feature will not change that. > I made an example to see how this would look. What’s the problem with “last in wins” like seen below? Seems pretty straightforward to me.

It already works that way (or at least it's supposed to, I haven't tested it right now).

Regards,
Sven