How to Jump Over the Hidden Hurdle

Version: 1.00.00 - last update: Monday, September 1st, 2014

WINAPI & VFP Internals (Home)


Hiding a PEM in Visual FoxPro makes this feature unavailable for reuse and takes it out of inheritance, right?
Are You Sure?

Intro

If you've ever wondered what VFP's Scope Resolution Operator really is good for, this is the place to stay!

VFP's Scope Resolution Operator (::)

On the internet, there is not much to read about the obviously orphaned scope resolution operator provided since VFP 3.0. Most comments run out on telling you that it is better today to use VFP's DODEFAULT() function to forward a message to the precursor.

Well, within the calling context of a simple DODEFAULT() they are right, all together!

But, there is more to say about the scope resolution operator than what's written in the help file, or any internet site I reached so far (while searching for already published information dealing with this topic).

This post assumes that you are familiar with what is written about the scope resolution operator in VFP's documentation. At least, you should have a clue what you can do with it, according to its help file entries.

What VFP's Scope Resolution Operator CAN and CAN NOT

Okay, we know, we have to use the class name instead of the instance name when invoking a Scope Resolution Operator Call. Let's assume, we want to invoke a method from one of our classes named "SuperContainer" using VFP's SROC like so:

llOkay = AbstractContainer::GetSecurityHandle(m.lcSecToken, This)

… where AbstractContainer is the name of a parent class somewhere 'above' the current one in the inheritance tree. Let's use the following inheritance pedigree as a basis to ask some questions further below:

Inheritance Example
(click to enlarge)

Can you answer the following questions?

    1. Inside a ClsCnt_CtrolsHost class instance, what class names can be used in a SRO call without raising an exception?
    2. Can you use a different method name on your ancestor class (can you invoke BaseContainer_GUI::Move() for example if such a method would exist)?
    3. Can you use the base class name of your class instance within your SRO invocation (can you invoke Container::Click() for example)?
    4. Can you use class names of other instantiated classes that are not part of your current inheritance pedigree (can you invoke SuperCollection::Add() for example if an instance of that collection-based class would exist in memory)?
    5. Can you use the class name of an descendant class (can you invoke ClsCtrlHost_Toolbar::Dock() for example if such a method would exist)?
    6. Can you invoke protected methods (can you invoke SuperContainer::RegisterItem() for example)?
    7. Can you invoke hidden methods (can you invoke AbstractContainer::GetSecurityHandle() for example)?
    8. Can you invoke method code "beyond" hidden methods (can you invoke _Container::GetSecurityHandle() for example)?
    9. Will the SRO invocation on a parent class trigger any event-bound delegates on your current class instance?
    10. Will a SRO invocation trigger VFP events at all?
    11. Will a SRO invocation cause the execution of DODEFAULT()s?
    12. At what inheritance level then does the DODEFAULT() pipelining start?
    13. Are there any behavioral differences between PRG-based, VCX-based, and Mixed (VCX->PRG-based) classes?
    14. Is it possible to introduce recursion (unwanted, or at will)?

As you can see, there's more about the VFP's Scope Resolution Operator than to think it's almost useless :-) Believe me, if you do know all about it, you will get one good new idea after the other how to employ Scope Resolution Operator Calls in unusual ways to solve unusual problems…

Ending for today…

One thing I would never do, even not in my wildest dreams, is to use the Scope Resolution Operator instead of a DODEFAULT(), at least in cases where a 'simple' DODEFAULT() is sufficient! The way I'm primarily using Scope Resolution Operator invocations is using them indirectly, like so:

lcRetVal = Evaluate(laAnchestors[3]+"::"+m.lcFeatureName+"()")

where the local laAnchestors array was filled using one of VFP's reflection-related function, like so:

= ACLASS(laAnchestors, This).

<to be continued…>


WINAPI & VFP Internals (Home)

2 comments:

  1. I'm guessing that this coincides with the other post in this section on "unknown types." My guess is that you're using the scope resolution operator to access instance level code of object arrays...

    I like to look at your teaser posts and see if I can figure out what you're going to post later.

    On a related subject: I can't wait for you to finish this post on the the scope resolution operator and your other post on the type-agnostic class methods. (Which I'm assuming are due to object arrays)

    I look forward to these posts, they can't come fast enough!

    -TRH

    ReplyDelete
  2. @TRH: Hi, thank you for your comment! You said: "My guess is that you're using the scope resolution operator to access instance level code of object arrays..."

    Well, VFP's Scope Resolution Operator (::) CANNOT be used to access INSTANCE LEVEL CODE (invoke methods of the current object), but only any ANCHESTOR CLASS LEVEL CODE the current class instance is inheriting from. That anchestor class code then gets executed WITHIN the MEMORY CONTEXT of the current class instance!

    BTW: What exactly do you mean with "to access instance level code of object arrays..."? Sounds a little bit too "blurred" to me:-)

    ReplyDelete