Alberto Narduzzi wrote 7 lines
An interface to a class (or its concept, anyway) is there for a reason. And
you should adhere to. I may also say that if you need to access a protected,
or private for what is worth, member of a (library...) class, then you
should revise your code... because either you're using the wrong class, or
your problem can be solved in a different, possibly more elegant, and surely
more OO compliant way ;-)
I totally disagree... :)
There are valid use cases where developers need access to protected methods. Here is a case in point (and I have many other examples too).
I implemented the Model-GUI-Mediator (MGM) design pattern to make any standard components (non-db) "object aware" for the tiOPF persistence framework. MGM allows me to bind object data to any standard components, and have two-way updating, without the need to create even more custom or descendant GUI components (this replaces the need for DB-aware components). Some of the mediators are implemented in a generic fashion, using base classes of GUI components so that that same mediator could be used for any descendant classes of that component (view).
eg: Below is some code for a TCustomEdit mediator. This mediators applies to any TCustomEdit descendants - and there are many of those. In the case below, we needed access to the ReadOnly property of TCustomEdit, but it was defined as protected (which was the correct thing to do for TCustomXXX components). In the code below, View is the component instance we are working with and is defined as TCustomEdit type - thus and can hold a reference to any TCustomEdit descendant.
type
// Friend class to get access to protected methods
THackCustomEdit = class(TCustomEdit);
class function TtiCustomEditMediatorView.ComponentClass: TClass;
begin
Result := TCustomEdit;
end;
function TtiCustomEditMediatorView.GetCurrentControlColor: TColor;
begin
if THackCustomEdit(View).ReadOnly then
result := ColorToRGB(ControlReadOnlyColor)
else
result := inherited GetCurrentControlColor;
end;
There is NO other way to implement this, except to create a mediator for each and every TCustomEdit descendants. Implementing the alternative would have been lots and lots of code duplication, and new mediators for each new TCustomEdit descendant that arrives in the market. Using the "friend class hack" means MUCH less code, and things still work perfectly.
Regards,
? - Graeme -
_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://fpgui.sourceforge.net