Sign in Join

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

Mailing lists / fpc-pascal / 2006-08

2.1.1 new protected

24 messages · 11 people · –

Reply by email Subscribe to this list Your subscription

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

Mattias Gaertner

Recently the behaviour of the 'protected' keyword has changed in fpc 2.1.1. Now I wonder how can I fix the code, that depends on this.

I have some base classes, that defines methods to let derived classes interact. These methods should not be accessed directly from the outside, so they are protected. But this does not work any longer. Of course I can safely typecast, but for aesthetic reasons it looks pretty bad coding style to typecast a class to the wrong class. For example:

-- unit1 -------------------------
  TMyClass = class
    FFlag: boolean;
  protected
    procedure InternalSetFlag(b: boolean);
  end;
-- unit2 -------------------------
  TDescendantClass1 = class(TMyClass)
  public
    procedure CallProtectedMethod(AnObject: TMyClass);
  end;
  TDescendantClass2 = class(TMyClass)
  end;
procedure TDescendantClass1.CallProtectedMethod(AnObject: TMyClass);
begin
  InternalSetFlag(true); // allowed
  AnObject.InternalSetFlag(true); // not allowed any longer
  TDescendantClass1(AnObject).InternalSetFlag(true); // allowed and works, but ugly
end;
-------------------------------

Any idea?

Mattias

Florian Klaempfl
to Mattias Gaertner
Mattias Gaertner wrote
Recently the behaviour of the 'protected' keyword has changed in fpc 2.1.1. Now I wonder how can I fix the code, that depends on this.

Redesign :)

Show quoted text 25 lines
I have some base classes, that defines methods to let derived classes interact. These methods should not be accessed directly from the outside, so they are protected. But this does not work any longer. Of course I can safely typecast, but for aesthetic reasons it looks pretty bad coding style to typecast a class to the wrong class. For example: -- unit1 ------------------------- TMyClass = class FFlag: boolean; protected procedure InternalSetFlag(b: boolean); end; -- unit2 ------------------------- TDescendantClass1 = class(TMyClass) public procedure CallProtectedMethod(AnObject: TMyClass); end; TDescendantClass2 = class(TMyClass) end; procedure TDescendantClass1.CallProtectedMethod(AnObject: TMyClass); begin InternalSetFlag(true); // allowed AnObject.InternalSetFlag(true); // not allowed any longer TDescendantClass1(AnObject).InternalSetFlag(true); // allowed and works, but ugly

Shouldn't be allowed either imo.

Show quoted text 11 lines
end; ------------------------------- Any idea? Mattias _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Michael Van Canneyt
to Florian Klaempfl
Florian Klaempfl wrote 39 lines
Mattias Gaertner wrote: > Recently the behaviour of the 'protected' keyword has changed in fpc 2.1.1. > Now I wonder how can I fix the code, that depends on this. Redesign :) > > I have some base classes, that defines methods to let derived classes > interact. > These methods should not be accessed directly from the outside, so they are > protected. But this does not work any longer. Of course I can safely > typecast, but for aesthetic reasons it looks pretty bad coding style to > typecast a class to the wrong class. For example: > > -- unit1 ------------------------- > TMyClass = class > FFlag: boolean; > protected > procedure InternalSetFlag(b: boolean); > end; > > -- unit2 ------------------------- > TDescendantClass1 = class(TMyClass) > public > procedure CallProtectedMethod(AnObject: TMyClass); > end; > > TDescendantClass2 = class(TMyClass) > end; > > procedure TDescendantClass1.CallProtectedMethod(AnObject: TMyClass); > begin > InternalSetFlag(true); // allowed > AnObject.InternalSetFlag(true); // not allowed any longer > TDescendantClass1(AnObject).InternalSetFlag(true); // allowed and works, > but ugly Shouldn't be allowed either imo.

Why not ?
In a descendent class you 'know' the protected method.

Michael.

Jonas Maebe
to Mattias Gaertner: Recently the behaviour of the 'protected' keyword has changed in fpc 2.1.1. Now I wonder…
Mattias Gaertner wrote 6 lines
I have some base classes, that defines methods to let derived classes interact. These methods should not be accessed directly from the outside, so they are protected. But this does not work any longer. Of course I can safely typecast, but for aesthetic reasons it looks pretty bad coding style to typecast a class to the wrong class.

Not only that, but you'll get a run time error when compiling with -CR.

Show quoted text 24 lines
For example: -- unit1 ------------------------- TMyClass = class FFlag: boolean; protected procedure InternalSetFlag(b: boolean); end; -- unit2 ------------------------- TDescendantClass1 = class(TMyClass) public procedure CallProtectedMethod(AnObject: TMyClass); end; TDescendantClass2 = class(TMyClass) end; procedure TDescendantClass1.CallProtectedMethod(AnObject: TMyClass); begin InternalSetFlag(true); // allowed AnObject.InternalSetFlag(true); // not allowed any longer TDescendantClass1(AnObject).InternalSetFlag(true); // allowed and works, but ugly

I think that this shouldn't be allowed either, to be honest. What you seem to want is some sort of "friend" classes like in C++. I doubt this will be added any time soon though.

Jonas

Florian Klaempfl
to Michael Van Canneyt: Why not ? In a descendent class you 'know' the protected method. Michael.
Michael Van Canneyt wrote 46 lines
On Fri, 11 Aug 2006, Florian Klaempfl wrote: > Mattias Gaertner wrote: >> Recently the behaviour of the 'protected' keyword has changed in fpc >> 2.1.1. >> Now I wonder how can I fix the code, that depends on this. > > Redesign :) > >> >> I have some base classes, that defines methods to let derived classes >> interact. >> These methods should not be accessed directly from the outside, so >> they are protected. But this does not work any longer. Of course I >> can safely typecast, but for aesthetic reasons it looks pretty bad >> coding style to typecast a class to the wrong class. For example: >> >> -- unit1 ------------------------- >> TMyClass = class >> FFlag: boolean; >> protected >> procedure InternalSetFlag(b: boolean); >> end; >> >> -- unit2 ------------------------- >> TDescendantClass1 = class(TMyClass) >> public >> procedure CallProtectedMethod(AnObject: TMyClass); >> end; >> >> TDescendantClass2 = class(TMyClass) >> end; >> >> procedure TDescendantClass1.CallProtectedMethod(AnObject: TMyClass); >> begin >> InternalSetFlag(true); // allowed >> AnObject.InternalSetFlag(true); // not allowed any longer >> TDescendantClass1(AnObject).InternalSetFlag(true); // allowed and >> works, but ugly > > > Shouldn't be allowed either imo. Why not ? In a descendent class you 'know' the protected method.

But only of the current instance, no?

Mattias Gaertner
to Florian Klaempfl: Redesign :) Shouldn't be allowed either imo.
Show quoted text 5 lines
Mattias Gaertner wrote: > Recently the behaviour of the 'protected' keyword has changed in fpc 2.1.1. > Now I wonder how can I fix the code, that depends on this. Redesign :)

Of FPC? Naaah, too much work. ;)

Of my code: Yes, but how?
Looking at the Delphi sources, I see that Borland has made many such methods public, which resulted in Code using the VCL the wrong way and creating VCL version dependent conflicts. I want to avoid this, and the old protected allowed that. But now I can't find any good alternative.

Show quoted text 27 lines
> I have some base classes, that defines methods to let derived classes interact. > These methods should not be accessed directly from the outside, so they are protected. But this does not work any longer. Of course I can safely typecast, but for aesthetic reasons it looks pretty bad coding style to typecast a class to the wrong class. For example: > > -- unit1 ------------------------- > TMyClass = class > FFlag: boolean; > protected > procedure InternalSetFlag(b: boolean); > end; > > -- unit2 ------------------------- > TDescendantClass1 = class(TMyClass) > public > procedure CallProtectedMethod(AnObject: TMyClass); > end; > > TDescendantClass2 = class(TMyClass) > end; > > procedure TDescendantClass1.CallProtectedMethod(AnObject: TMyClass); > begin > InternalSetFlag(true); // allowed > AnObject.InternalSetFlag(true); // not allowed any longer > TDescendantClass1(AnObject).InternalSetFlag(true); // allowed and works, but ugly Shouldn't be allowed either imo.

What's the alternative?

Mattias

Michael Van Canneyt
to Florian Klaempfl: But only of the current instance, no?
Florian Klaempfl wrote 49 lines
Michael Van Canneyt wrote: > > > On Fri, 11 Aug 2006, Florian Klaempfl wrote: > >> Mattias Gaertner wrote: >>> Recently the behaviour of the 'protected' keyword has changed in fpc >>> 2.1.1. >>> Now I wonder how can I fix the code, that depends on this. >> >> Redesign :) >> >>> >>> I have some base classes, that defines methods to let derived classes >>> interact. >>> These methods should not be accessed directly from the outside, so they >>> are protected. But this does not work any longer. Of course I can safely >>> typecast, but for aesthetic reasons it looks pretty bad coding style to >>> typecast a class to the wrong class. For example: >>> >>> -- unit1 ------------------------- >>> TMyClass = class >>> FFlag: boolean; >>> protected >>> procedure InternalSetFlag(b: boolean); >>> end; >>> >>> -- unit2 ------------------------- >>> TDescendantClass1 = class(TMyClass) >>> public >>> procedure CallProtectedMethod(AnObject: TMyClass); >>> end; >>> >>> TDescendantClass2 = class(TMyClass) >>> end; >>> >>> procedure TDescendantClass1.CallProtectedMethod(AnObject: TMyClass); >>> begin >>> InternalSetFlag(true); // allowed >>> AnObject.InternalSetFlag(true); // not allowed any longer >>> TDescendantClass1(AnObject).InternalSetFlag(true); // allowed and >>> works, but ugly >> >> >> Shouldn't be allowed either imo. > > Why not ? In a descendent class you 'know' the protected method. But only of the current instance, no?

Well, nothing is said about this in the manuals; For me this is up to discussion. It seems normal to me that it is not just the current instance. You KNOW this method is there, in a descendent, so it seems logical that you know that it exists for another instance as well.

Personally, I think we should allow use of protected methods in a descendent, also for other instances. In the above example:

   AnObject.InternalSetFlag(true);

Should work. But since this is not Delphi compatible, I think this should be in Objpas mode only.

Michael.

Martin Schreiber
to Mattias Gaertner: On Fri, 11 Aug 2006 13:42:49 +0200 Of FPC? Naaah, too much work. ;) Of my code: Yes, but…
Mattias Gaertner wrote 17 lines
On Fri, 11 Aug 2006 13:42:49 +0200 Florian Klaempfl wrote: > Mattias Gaertner wrote: > > Recently the behaviour of the 'protected' keyword has changed in fpc > > 2.1.1. Now I wonder how can I fix the code, that depends on this. > > Redesign :) Of FPC? Naaah, too much work. ;) Of my code: Yes, but how? Looking at the Delphi sources, I see that Borland has made many such methods public, which resulted in Code using the VCL the wrong way and creating VCL version dependent conflicts. I want to avoid this, and the old protected allowed that. But now I can't find any good alternative.

Agreed, same for MSEide+MSEgui.
In a big GUI system it is not possible to handle all low level stuff in a simple class hierarchy, there must be a way to access protected methods of other instances and classes in other units.

What's the alternative?

To have most of internal procedures public with a comment "for internal use only", I really don't like it, or to have all code in a single file, I don't like it too.
What about "friend units'?

Martin

Graeme Geldenhuys
to Michael Van Canneyt: Well, nothing is said about this in the manuals; For me this is up to discussion. It…
Michael Van Canneyt wrote
It seems normal to me that it is not just the current instance. You KNOW this method is there, in a descendent, so it seems logical that you know that it exists for another instance as well.

Coming from a Delphi background, I disagree here. As I understood the Delphi docs, protected methods are only visible in the current instance (decendant), and not instances passed in as parameters.

Reading the docs again, I am not sure what happens when both those classes appear in the same unit. This then becomes like the "friend" classes used in C++ and C# and might be allowed in such a case... Quite confusing... :-)

Here is a snippet of the Kylix 3 docs:

------------------------
... See attached image, I couldn't cut and paste from CLX.... ------------------------

Regards,
- Graeme -

There's no place like 127.0.0.1
Graeme Geldenhuys
to Graeme Geldenhuys

I managed to Copy and Paste the text, for thouse that can't view the attached image from my previous post...

---------------------------
A private member is invisible outside of the unit or program where its class is declared. In other words, a private method cannot be called from another module, and a private field or property cannot be read or written to from another module. By placing related class declarations in the same module, you can give the classes access to one another's private members without making those members more widely accessible.

A protected member is visible anywhere in the module where its class is declared and from any descendant class, regardless of the module where the descendant class appears. A protected method can be called, and a protected field or property read or written to, from the definition of any method belonging to a class that descends from the one where the protected member is declared. Members that are intended for use only in the implementation of derived classes are usually protected.

A public member is visible wherever its class can
be referenced
---------------------------

Regards,
Graeme.

Graeme Geldenhuys wrote 22 lines
On 8/11/06, Michael Van Canneyt wrote: > It seems normal to me that it is not just the current instance. You KNOW this > method is there, in a descendent, so it seems logical that you know that it > exists for another instance as well. Coming from a Delphi background, I disagree here. As I understood the Delphi docs, protected methods are only visible in the current instance (decendant), and not instances passed in as parameters. Reading the docs again, I am not sure what happens when both those classes appear in the same unit. This then becomes like the "friend" classes used in C++ and C# and might be allowed in such a case... Quite confusing... :-) Here is a snippet of the Kylix 3 docs: ------------------------ ... See attached image, I couldn't cut and paste from CLX.... ------------------------ Regards, - Graeme -
There's no place like 127.0.0.1
Mattias Gaertner
to Graeme Geldenhuys: Coming from a Delphi background, I disagree here. As I understood the Delphi docs,…
Show quoted text 8 lines
On 8/11/06, Michael Van Canneyt wrote: > It seems normal to me that it is not just the current instance. You KNOW this > method is there, in a descendent, so it seems logical that you know that it > exists for another instance as well. Coming from a Delphi background, I disagree here. As I understood the Delphi docs, protected methods are only visible in the current instance (decendant), and not instances passed in as parameters.

It does not matter how you got the instance, via parameter, variable or function. Only the class of the instance matters.

The screenshot says:
A protected member is visible [...] from any descendant class. A protected method can be called from the definition of any method belonging to a class that descends from the one where the protected member is declared.

Where do you read here anything about 'current instance'?

IMO the old 'Protected' was very easy to explain to people: "Is the same as Private, except that the members of a Protected section are also accessible to descendent types, even if they are implemented in other modules." No exceptions. Pretty straight.

And it was very Delphi compatible. I mean, how many Delphians noticed the difference at all? It didn't hurt and gave more flexibility. So, I second Michael's proposal to at least keep it in mode objfpc.

Show quoted text 10 lines
Reading the docs again, I am not sure what happens when both those classes appear in the same unit. This then becomes like the "friend" classes used in C++ and C# and might be allowed in such a case... Quite confusing... :-) Here is a snippet of the Kylix 3 docs: ------------------------ ... See attached image, I couldn't cut and paste from CLX.... ------------------------

Mattias

Alexandre Leclerc
to Mattias Gaertner

2006/8/11, Mattias Gaertner :

Show quoted text 24 lines
On Fri, 11 Aug 2006 14:49:16 +0200 "Graeme Geldenhuys" wrote: > On 8/11/06, Michael Van Canneyt wrote: > > It seems normal to me that it is not just the current instance. You KNOW this > > method is there, in a descendent, so it seems logical that you know that it > > exists for another instance as well. > > Coming from a Delphi background, I disagree here. As I understood the > Delphi docs, protected methods are only visible in the current > instance (decendant), and not instances passed in as parameters. It does not matter how you got the instance, via parameter, variable or function. Only the class of the instance matters. The screenshot says: A protected member is visible [...] from any descendant class. A protected method can be called from the definition of any method belonging to a class that descends from the one where the protected member is declared. Where do you read here anything about 'current instance'? IMO the old 'Protected' was very easy to explain to people: "Is the same as Private, except that the members of a Protected section are also accessible to descendent types, even if they are implemented in other modules." No exceptions. Pretty straight.

Yep this is it and I always understood it like that.

And it was very Delphi compatible. I mean, how many Delphians noticed the difference at all? It didn't hurt and gave more flexibility. So, I second Michael's proposal to at least keep it in mode objfpc.

I would make it work if you are actually in a descendent...? Because for me typecasting AnObject to make it fit with a descendent and using the protected method is a violation of the rule. If you are in a descendent then you can call the protected method. Then a typecast would not be required either sing you know the descendent.

So your initial example is acceptable. Here a note/comment I add and a unit3 example to explain the simple point I raised.

-- unit2 -------------------------
procedure TDescendantClass1.CallProtectedMethod(AnObject: TMyClass);
begin
 InternalSetFlag(true); // allowed
 AnObject.InternalSetFlag(true); // allowed (why not?), you know the descendent?
 TDescendantClass1(AnObject).InternalSetFlag(true); // allowed and
works, but ugly
end;
-- unit3 -------------------------
ADescendantClass1 = TDescendantClass1;
ADescendantClass2 = TDescendantClass2;
procedure Form1.TryAccessProtected(AnObject: TMyClass);
begin
 AnObject.InternalSetFlag(true); // not allowed
 TDescendantClass1(AnObject).InternalSetFlag(true); // not allowed
end;
-------------------------------

Best Regards.

Alexandre Leclerc
Graeme Geldenhuys
to Mattias Gaertner: On Fri, 11 Aug 2006 14:49:16 +0200 It does not matter how you got the instance, via…
Mattias Gaertner wrote
Where do you read here anything about 'current instance'?

Maybe not in that snippet of text, but I read it somewhere... ;-)

And it was very Delphi compatible. I mean, how many Delphians noticed the difference at all? It didn't hurt and gave more flexibility. So, I second Michael's proposal to at least keep it in mode objfpc.

Maybe it is only me, but I am used to the Delphi way. It made you think twice about accessing methods deep in a hierachy (normally hidden). I do agree it will make it easier to access protected methods, but not so sure if that is a good thing.

I created a few classes as shown below, but doing this made me think about it first, before blindly accessing methods.

  { Create a friend class so we can access the protected AddAction method. }
  TActionListFriend = class(TActionList)
  end;

And used it as follows....

  aOK                     := TAction.Create(self);
  aOK.Caption             := csOK;
  aOK.OnExecute           := @aOKExecute;
  { Must add to list otherwise it doesn't execute }
  TActionListFriend(FActionList).AddAction(aOK);

This reminds me, Mattias, must TActionList.AddAction be protected? I had to do the above to create actionlists via code and get the actions to execute correctly.

Regards,
- Graeme -

There's no place like 127.0.0.1
Mattias Gaertner
to Graeme Geldenhuys
On 8/11/06, Mattias Gaertner wrote: > Where do you read here anything about 'current instance'? Maybe not in that snippet of text, but I read it somewhere... ;-)

:)

Show quoted text 7 lines
> And it was very Delphi compatible. I mean, how many Delphians noticed the difference at all? It didn't hurt and gave more flexibility. So, I second Michael's proposal to at least keep it in mode objfpc. Maybe it is only me, but I am used to the Delphi way. It made you think twice about accessing methods deep in a hierachy (normally hidden). I do agree it will make it easier to access protected methods, but not so sure if that is a good thing.

It is has advantages and there is no good alternative. The only disadvantage I see, is that code written with FPC would not work with this commercial third party compiler. That's why mode Delphi should use the new protected. But why mode objfpc?

I created a few classes as shown below, but doing this made me think about it first, before blindly accessing methods.

You can only access public methods *blindingly*.
Protected methods can only be used by descendants. That's why Martin and I meant with the 'public' hell of the VCL.

Show quoted text 16 lines
{ Create a friend class so we can access the protected AddAction method. } TActionListFriend = class(TActionList) end; And used it as follows.... aOK := TAction.Create(self); aOK.Caption := csOK; aOK.OnExecute := @aOKExecute; { Must add to list otherwise it doesn't execute } TActionListFriend(FActionList).AddAction(aOK); This reminds me, Mattias, must TActionList.AddAction be protected? I had to do the above to create actionlists via code and get the actions to execute correctly.

Thanks for the good example. With the protected method you can easily do dangerous things, like adding an action twice or forgetting to remove it. With the 'protected' AddAction you could do such things only with dirty tricks like the above. The normal way is:

aOK.ActionList:=FActionList;

This is not only shorter, but also safe.

Mattias

Graeme Geldenhuys
to Mattias Gaertner
Mattias Gaertner wrote 5 lines
Thanks for the good example. With the protected method you can easily do dangerous things, like adding an action twice or forgetting to remove it. With the 'protected' AddAction you could do such things only with dirty tricks like the above. The normal way is: aOK.ActionList:=FActionList; This is not only shorter, but also safe.

Ah... Never saw the TAction.ActionList property. Thanks for the tip! Will be updating my code shortly and get rid of that hack. :-)

Regards,
Graeme.

There's no place like 127.0.0.1
Marc Weustink
to Martin Schreiber: Agreed, same for MSEide+MSEgui. In a big GUI system it is not possible to handle all low…
Martin Schreiber wrote 28 lines
On Friday 11 August 2006 13.58, Mattias Gaertner wrote: > On Fri, 11 Aug 2006 13:42:49 +0200 > > Florian Klaempfl wrote: >> Mattias Gaertner wrote: >>> Recently the behaviour of the 'protected' keyword has changed in fpc >>> 2.1.1. Now I wonder how can I fix the code, that depends on this. >> Redesign :) > Of FPC? Naaah, too much work. ;) > > Of my code: Yes, but how? > Looking at the Delphi sources, I see that Borland has made many such > methods public, which resulted in Code using the VCL the wrong way and > creating VCL version dependent conflicts. I want to avoid this, and the old > protected allowed that. But now I can't find any good alternative. > Agreed, same for MSEide+MSEgui. In a big GUI system it is not possible to handle all low level stuff in a simple class hierarchy, there must be a way to access protected methods of other instances and classes in other units. > What's the alternative? > To have most of internal procedures public with a comment "for internal use only", I really don't like it, or to have all code in a single file, I don't like it too. What about "friend units'?

Or something like as it is "solved" in delphi with helper classes (p215). (Maybe we can also implement the strict version (p168))

http://info.borland.com/techpubs/delphi/Delphi2006/Reference.pdf

Marc

Martin Schreiber
to Marc Weustink
Marc Weustink wrote 12 lines
>> What's the alternative? > > To have most of internal procedures public with a comment "for internal > use only", I really don't like it, or to have all code in a single file, > I don't like it too. > What about "friend units'? Or something like as it is "solved" in delphi with helper classes (p215). (Maybe we can also implement the strict version (p168)) http://info.borland.com/techpubs/delphi/Delphi2006/Reference.pdf

It seems that FPC 2.1.1 implements the behaviour of Delphi 2006 'strict protected' by default.

In MSEgui I have the problem that there is too much low level stuff to fit in one unit and the dependences are too complex to be mapped into a simple class hierarchy. Up to time I did as follows to access low level elements of classes in other units:
"
implementation
type
TLowLevelClassInOtherUnit1 = class(TLowLevelClassInOtherUnit);

procedure TLowLevelClassInThisUnit.DoSomething;
begin
TLowLevelClassInOtherUnit1

            (InstanceOfTLowLevelClassInOtherUnit).DoSomethingProtected;

end;
"
It is ugly, produces warnings and is possibly forbidden in FPC 2.1.1 (I don't know). A more elegant solution would be to have something like 'friend units' where protected class members are visible:
"
unit secondlowlevelunit;
interface
uses
firstlowlevelunit,highlevelunit;
friends //use appropriate keyword and notation firstlowlevelunit;
"

-> In "secondlowlevelunit" all protected class members of "firstlowlevelunit" are visible, protected class members of "highlevelunit" are visible in descendant classes.

Martin

Marc Weustink
to Martin Schreiber
Martin Schreiber wrote 14 lines
On Friday 11 August 2006 20.35, Marc Weustink wrote: >>> What's the alternative? >> To have most of internal procedures public with a comment "for internal >> use only", I really don't like it, or to have all code in a single file, >> I don't like it too. >> What about "friend units'? > Or something like as it is "solved" in delphi with helper classes (p215). > (Maybe we can also implement the strict version (p168)) > > http://info.borland.com/techpubs/delphi/Delphi2006/Reference.pdf > It seems that FPC 2.1.1 implements the behaviour of Delphi 2006 'strict protected' by default.

I don't think so, the delphi 2006 strict syntax is more strict. The example you gave below is (afaik) still possible in FPC, which wouldn't if it was strict.

Marc

Show quoted text 36 lines
In MSEgui I have the problem that there is too much low level stuff to fit in one unit and the dependences are too complex to be mapped into a simple class hierarchy. Up to time I did as follows to access low level elements of classes in other units: " implementation type TLowLevelClassInOtherUnit1 = class(TLowLevelClassInOtherUnit); procedure TLowLevelClassInThisUnit.DoSomething; begin TLowLevelClassInOtherUnit1 (InstanceOfTLowLevelClassInOtherUnit).DoSomethingProtected; end; " It is ugly, produces warnings and is possibly forbidden in FPC 2.1.1 (I don't know). A more elegant solution would be to have something like 'friend units' where protected class members are visible: " unit secondlowlevelunit; interface uses firstlowlevelunit,highlevelunit; friends //use appropriate keyword and notation firstlowlevelunit; " -> In "secondlowlevelunit" all protected class members of "firstlowlevelunit" are visible, protected class members of "highlevelunit" are visible in descendant classes. Martin _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Peter Vreman
to Marc Weustink
Show quoted text 15 lines
>>>>What's the alternative? >>>To have most of internal procedures public with a comment "for internal >>>use only", I really don't like it, or to have all code in a single file, >>>I don't like it too. >>>What about "friend units'? >>Or something like as it is "solved" in delphi with helper classes (p215). >>(Maybe we can also implement the strict version (p168)) >> >>http://info.borland.com/techpubs/delphi/Delphi2006/Reference.pdf >It seems that FPC 2.1.1 implements the behaviour of Delphi 2006 >'strict protected' by default. I don't think so, the delphi 2006 strict syntax is more strict. The example you gave below is (afaik) still possible in FPC, which wouldn't if it was strict.

strict is also implemented in FPC and it is more strict.

Peter

Florian Klaempfl
to Marco van de Voort
Marco van de Voort wrote 6 lines
> It is ugly, produces warnings and is possibly forbidden in FPC 2.1.1 (I don't > know). A more elegant solution would be to have something like 'friend units' > where protected class members are visible: I wonder what the use of making a private/public/protected distinction is in the first place, if USES'ing units can override :) Borland realized this as well and added the strict private/protected ...
Martin Schreiber
to Marco van de Voort: I wonder what the use of making a private/public/protected distinction is in the first…
Marco van de Voort wrote 7 lines
> It is ugly, produces warnings and is possibly forbidden in FPC 2.1.1 (I > don't know). A more elegant solution would be to have something like > 'friend units' where protected class members are visible: I wonder what the use of making a private/public/protected distinction is in the first place, if USES'ing units can override it at will.

In a tool library:

public -> interface for the library users, use it without knowledge of the internals.

protected -> interface for the library developers, use it if you know what you do. Use strict protected if you want to secure encapsulate things.

private -> secure encapsulated class items.

Note that I had to use 'cracker classes' in MSEgui to access private FPC class items to implement workarounds...
I must repeat:
It is not possible to develop a complex system in a clean single class hierarchy, especially not if you use foreign units which are not under your control . I know it because I tried it...

Martin

Michael Van Canneyt
to Martin Schreiber
Martin Schreiber wrote 25 lines
On Sunday 13 August 2006 13.27, Marco van de Voort wrote: >> It is ugly, produces warnings and is possibly forbidden in FPC 2.1.1 (I >> don't know). A more elegant solution would be to have something like >> 'friend units' where protected class members are visible: > > I wonder what the use of making a private/public/protected distinction is > in the first place, if USES'ing units can override it at will. > In a tool library: public -> interface for the library users, use it without knowledge of the internals. protected -> interface for the library developers, use it if you know what you do. Use strict protected if you want to secure encapsulate things. private -> secure encapsulated class items. Note that I had to use 'cracker classes' in MSEgui to access private FPC class items to implement workarounds... I must repeat: It is not possible to develop a complex system in a clean single class hierarchy, especially not if you use foreign units which are not under your control . I know it because I tried it...

No. It just means the classes are designed wrong.

If you need to access directly private class fields, I think there are serious design flaws in your code.

Michael.

memsom
to Michael Van Canneyt
No. It just means the classes are designed wrong.

Very true. There are a number of places in Delphi's VCL where this is true... for D5 at least.

If you need to access directly private class fields, I think there are serious design flaws in your code.

Class "crackers" only give access to protected members - well in Delphi at any rate.

type
  TCrackControl = class(TControl);
var
  _label: TLabel;

...

  TCrackControl(_label).Text := 'I can do this now';

This is pointless as the Text and Caption of a label map to the same internal data, but using this method it demonstrates access to internals.

As to why Borland made a distinction between Caption and Text properties.. another debate ;-)