[Lazarus] TImage - Getting image properties in 'canvas space'

Graeme Geldenhuys graemeg.lists at gmail.com
Thu Apr 19 09:44:10 CEST 2012


On 19 April 2012 00:04, Alberto Narduzzi <albertonarduzzi at yahoo.com> wrote:
>
> 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




More information about the Lazarus mailing list