Subject Re: [IBO] TIB_GridInplaceEdit
Author Frank Ingermann
Hi Geoff / Guido,

i don't know ibo very well yet, but i do know delphi since it's there :-)
so please give me a chance to tell you something *you* may not know, it's
always the other way around when it comes to ibo <g>...

if Assigned( InPlaceEditor ) and
(TIP_GridInplaceEdit(InPlaceEditor).EditStyle = esDate) then

"hard" typecasts in the style of TForceClass(dontknowwhatclass) are always
unsafe, *unless* you really know that the thing in braces is really
of class TForceClass (see below). Otherwise you will very likely get AV's,
if *either* InplaceEditor is NIL *or* not of the type you cast it to...
The Assigned check only tells you whether all 32bits of the pointer
are 0 or not (a.k.a. NIL), it makes no class compatibilty check whatsoever.

if Assigned( InPlaceEditor ) and
(InplaceEditor is TIB_GridInplaceEdit) and
(TIP_GridInplaceEdit(InPlaceEditor).EditStyle = esDate) then

this is safe, although a little redundant. The IS operator returns
true when the pointer a) IS assigned *and* b) IS of the class you compare
it with (or at least inherits from it (!)), so when you use IS there's
no need for "if Assigned()". If you want to know whether your obj var
has *exactly* the same class then what you compare against, use

IF InplaceEditor.ClassType = TIB_GridEditor.ClassType

if InplaceEditor only INHERITS from TIB_GridEditor this will be False!
Note that you can access the ClassType property of the *class* TIB_GridEditor,
because in TObject this is declared as a "class function", so you don't
need an instance (or "existing object pointer") to call that func.

the simplest *safe* form, and the best readable i think for what Guido
originally wanted to do is:

if (InplaceEditor is TIB_GridInplaceEdit) and
((InplaceEditor as TIB_GridInplaceEdit).EditStyle = esDate) then

(the best thing is that you can copypaste the line and just change
the "i" to "a" - works even faster with a kbd macro :)

or, if you have to do more with the inplaceeditor once you have it:

if InplaceEditor is TIB_GridInplaceEdit then
with InplaceEditor as TIB_GridInplaceEdit do
if EditStyle = esDate then...
// you're now safe inside the namespace of InplaceEditor
// but you can still access the props of Self. e.g.:
if Tag <> Self.Tag then...
// the first Tag is that of InplaceEditor, the Self.Tag is that
// of the instance that is made of this actual code

> AFAIK class(object) are not checked, but forced to the particular type
> at compile time. As such this is much more efficient where the type
> is known (since no runtime checking is required). It is also
> convenient for hacks, as you are discovering. (someone please correct
> me if I am wrong here, since I cannot find explicit confirmation in
> the online doco)

i guess the "hacks" you mean are the cases when hard-typecasting some obj
into the *wrong* class will actually work safely. (you can create
"parallel classes" to an obj class if you're aware of the impact on the
VMT (virtual method table) and the way delphi looks up get&set methods
for props - i wouldn't recommend that, though)

> The code works for Jason because TIB_Grid actually creates inplace
> edit of the type requested and so the runtime type check succeeds.

I consider this *not* a hack, since Jason knows by program logic that this
*can* only be of the type he expects, and in these cases (and imo only in
these) "hard" typecasts are allowed/clean/safe...

oh, btw.. hacks... the next is a hack, but a safe one:

procedure listbox1Click (Sender: TObject);
lbx : TListBox ABSOLUTE Sender; // lbx lies at the same mem adr as Sender
if Sender IS TListbox then

Sorry this all went a bit off-topic...
but delphi is such a powerful and beautiful oop language, and many things can
be done so easily once you found the right way... so i thought this little
introduction to object class 'sql' might be of help for some of you :-)

regards & fun with delphi!,