Jim,
NODEFAULT and ::/DoDefault() are two different animals.
NODEFAULT is to prevent the automatic execution of the VFP BaseClass method code when all of the overridden code has executed. It's useful for two things 1) to prevent the BaseClass behavior entirely, and 2) to change when the BaseClass behavior occurs. And you are right about it being able to be executed at any time. I think of it as a flag set, that gets tested to conditionally execute the BaseClass behavior.
Thing 1: you want to prevent the A key from being entered in a textbox:
procedure KeyPress
lparameter nKeyCode, nShift
if ( nKeyCode = 65 )
nodefault
endif
Thing 2: change the order (this is my cTextBox.GotFocus)
if ( this.SelectOnEntry )
TextBox::GotFocus()
nodefault
this.SelStart = 0
do case
case ( this.MaxLength > 0 )
this.SelLength = this.MaxLength
case ( len( this.InputMask ) > 0 )
this.SelLength = len( this.InputMask )
endcase
)
endif
The explicit call to the BaseClass behavior is made
TextBox::GotFocus() because it sets the SelStart and SelLength properties, which I'm about to modify. The nodefault is issued because otherwise we'd get another execution of the BaseClass behavior automatically at the end of my overridden code and it would undo all of the work of my code.
Ok so
NODEFAULT only prevents the automatic execution of the VFP BaseClass behavior after the overridden method code It has
NOTHING to do with overridden code anywhere up the class tree.
:: and DoDefault() control the execution of our overridden method code in the class tree.
DoDefault() there is a big kettle of worms, and to be honest I rarely use it, I still hardcode :: calls. Most of the time you don't see a problem, because most of the time the VFP BaseClass behaviors to not produce "observeable" effects. But DoDefault() when issued from a subclass to an
empty ParentClass method will cause an execution of the VFP BaseClass behavior, and you'll get the automatic execution at the end. Issuing a :: call to the ParentClass does not cause this duplication to happen. So it's only going to happen to class trees two or more levels deep. This is a bug in my opinion, although not everyone in the VFP community agrees. Our subclasses should not have to know whether or not the class they are derived from has any code in the method. I first ran into this last summer while working on a txtDate class derived from my cTextBox class. The cTextBox.KeyPress() method is not overridden. Here's the relevant code from txtDate.KeyPress():
LPARAMETERS nKeyCode, nShiftAltCtrl
local lcKey, lnMonth, lnDay, lnYear
lcKey = upper( chr( nKeyCode ) )
if ( this.mlUseArrow )
do case
case nKeyCode = 5
lcKey = '-'
case nKeyCode = 24
lcKey = '+'
case ( ( nKeyCode = 56 ) and ( nShiftAltCtrl = 1 ) )
lcKey = 'M'
case ( ( nKeyCode = 50 ) and ( nShiftAltCtrl = 1 ) )
lcKey = 'H'
endcase
endif
if ! ( lcKey $ "T+-=MHYRE" )
return
endif
nodefault
cTextBox::KeyPress( nKeyCode, nShiftAltCtrl )
The only thime you are going to see this is when the VFP BaseClass really does something you can detect, like KeyPress, GotFocus. Events like MouseDown who can tell that you actually made VFP display the pushed down image of a button once or twice, you can't unless traced the code with something like CodeView.
Now if you go put
any code in the cTextBox.KeyPress() method DoDefault() would work just like cTextBox::KeyPress(). And that's where I feel the bug is, it shouldn't behave differently depending on whether or not there is code in the ParentClass method.
I've always thought DoDefault() was a shortcut, a way of coding a subclass without putting a hard-coded reference to the ParentClass::Method() in your overridden code.
Now back to the original question. Sometimes you want your overridden code to execute before the ParentClass, sometimes after, and sometimes in the middle of your overridden code. I'd say 98% of the time my code looks like:
ParentClass::Method()
*augmentation code here
1.99% of the time it's:
*augmentation code here
ParentClass::Method()
and 0.01%
*augmentation code here
ParentClass::Method()
*more augmentation code here
It just really depends on what the overridden code up the class tree is doing to know when it needs to be executed.
>Since NODEFAULT can be placed *anywhere* in its relevant code to perform its work (implying to me that 'default' is always done AFTER supplied stuff), then wouldn't it follow that DODEFAULT would also execute at a specific "spot" REGARDLESS of where it is placed?
>
>If not, then should we not be told, in view of what we are told for NODEFAULT?