Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Anomaly/Bug in VFP?

Status
Not open for further replies.

darrellblackhawk

Programmer
Aug 30, 2002
846
US
* Here's a little anomaly

* When the the go() method is called on CConcreteClass
* the hidden property "cKey" of oHidden2 is
* visible to CConcreteClass.

* cKey is not visible to CConcreteClass in any
* other aggregated object.

* At the outer "set step on" things are as expected

* hmmmmm....

* I guess it kinda makes sense since oHidden2 is defined
* as a hidden property of CConcreteClass, but I don't think so.

* Is this a bug in VFP?
Code:
local o
o = createobject("CConcreteClass")
o.go()

set step on

define class CConcreteClass as custom
  add object oHidden1 as CAggregateWithHiddenProp
  add object protected oHidden2 as CAggregateWithHiddenProp

  add object oProtected1 as CAggregateWithProtectedProp
  add object protected oProtected2 as CAggregateWithProtectedProp

  procedure go
    set step on
  endproc

enddefine


define class CAggregateWithHiddenProp as custom

  hidden cKey
  cKey = ""

enddefine

define class CAggregateWithProtectedProp as custom

  protected cKey
  cKey = ""

enddefine
 
I should have said defined as a protected property of
CConcreteClass.

Now it really doesn't make sense. :-(

Darrell
 
darrellblackhawk,

That certainly is odd and I can't make out the logic, to me it looks like a bug.

Just some clarification for others reading this thread and trying Darrell's code:

VFP Help File said:
By default, properties and methods in a class definition are Public...
Public Access is available from anywhere in an application.


Protected Restricts access to the property to class members and subclasses can access protected properties. Object instances cannot access this property.


Hidden Restricts access to the property to class members only. Object instances and subclasses cannot access hidden properties.

Here's a code snippet to run just in case some might think that the debugger is somehow affecting the visibility
Code:
local o
o = createobject("CConcreteClass")
o.go()

define class CConcreteClass as custom
  add object oHidden1 as CAggregateWithHiddenProp
  add object protected oHidden2 as CAggregateWithHiddenProp

  add object oProtected1 as CAggregateWithProtectedProp
  add object protected oProtected2 as CAggregateWithProtectedProp

  procedure go
  	clear
	ON ERROR ??"cKey COULD NOT be seen!"
	?"this.oHidden1.cKey Value:"
    ?this.oHidden1.cKey
    ?
	?"this.oHidden2.cKey Value:"
    ?this.oHidden2.cKey
    ?
	?"this.oProtected1.cKey Value:"
    ?this.oProtected1.cKey
    ?
	?"this.oProtected2.cKey Value:"
    ?this.oProtected2.cKey
  endproc
enddefine


define class CAggregateWithHiddenProp as custom
  hidden cKey
  cKey = "cKey CAN Be Seen!"
enddefine

define class CAggregateWithProtectedProp as custom
  protected cKey
  cKey = "cKey CAN Be Seen!"
enddefine

boyd.gif

 
The real quandry (pretty much ensures that this is a bug) is that this.oProtected2.cKey cannot be seen, but this.oHidden2.cKey can be seen. Since when does a protected object with a protected property have a lower visibility than a protected object with a hidden property?

boyd.gif

 
My sentiments exactly!

I'm still using an older version of VFP(6), so it would be
nice if someone could confirm that this behavior is
either fixed, or is consistently flawed in all newer
versions.

Darrell
 
I found this (bug?) while trying to figure out how to
allow editing of programs that create hierarchical classes
without getting the infamous: “Remove classes from memory
dialog” after the program ran.

[Example of issue:]

If you instance only one of the concrete classes at a
time, run the skeletal code below, and then attempt to
edit the prg, you won’t get the dialog: “Remove classes
from memory”. If you instance both concrete classes:
CStdSocket & CSecSocket, you will get the dialog after
attempting to edit the prg.

BTW. This behavior occurs whether or not the encapsulated
classes: CCompression & CEncryption are added to the
respective classes: CSocket & CSecSocket.


Hmmm…

Code:
* Test the dialog showing problem ->
#define nInstanceClasses 0 &&, 1, or 2
* When nInstanceClasses == 2, you'll get the dialog

local oStdSocket, oSecSocket

do case
  case nInstanceClasses == 0
    oStdSocket = createobject("CStdSocket")
  case nInstanceClasses == 1
    oSecSocket = createobject("CSecSocket")
  case nInstanceClasses == 2
    oStdSocket = createobject("CStdSocket")
    oSecSocket = createobject("CSecSocket")
endcase
* <-


* Abstract socket class
define class CSocket as custom
  add object protected oCmpr as CCompression

  procedure send
    lparam sStream, nChunkSize, bUseCompression

  endproc
enddefine

* Concrete standard socket class
define class CStdSocket as CSocket

enddefine

* Concrete secure socket class
define class CSecSocket as CSocket

  add object oEncr as CEncryption

  procedure send
    lparam sStream, nChunkSize, bUseCompression, cKey, nEncrMethod
    local nSuccess


    return nSuccess
  endproc

enddefine

* Compression class.
* Aggregated into abstract CSocket class
define class CCompression as custom
  protected nComprMethod
  nComprMethod = 0

  function CompressBytes
    lparam sStream, nComprMethod
    local nSuccess
    nSuccess = 1
    if !(vartype(sStream)=="C".and.len(sStream)>0)
      nSuccess = -1
    else

      with this
        .nComprMethod = iif(vartype(nComprMethod)=="N",nComprMethod,0)
        * <- Compression code here

        * ->

      endwith
    endif

    return nSuccess
  endfunc

  function DeCompressBytes
    lparam sStream, nComprMethod
    local nSuccess
    nSuccess = 1
    if !(vartype(sStream)=="C".and.len(sStream)>0)
      nSuccess = -1
    else

      with this
        .nComprMethod = iif(vartype(nComprMethod)=="N",nComprMethod,0)
        * <- Decompression code here

        * ->

      endwith
    endif

    return nSuccess
  endfunc

enddefine


* Encryption class.
* Aggregated into concrete CSecSocket class
define class CEncryption as custom
  protected cKey, nEncrMethod
  cKey = ""
  nEncrMethod = 0

  function EncryptBytes
    lparam sStream, cKey, nEncrMethod
    local nSuccess
    nSuccess = 1
    if !(vartype(sStream)=="C".and.len(sStream)>0)
      nSuccess = -1
    else

      with this
        .cKey = iif(vartype(cKey)=="C",cKey,"")
        .nEncrMethod = iif(vartype(nEncrMethod)=="N",nEncrMethod,0)
        * <- Encryption code here

        * ->
      endwith

    endif

    return nSuccess
  endfunc

  function DecryptBytes
    lparam sStream, cKey, nEncrMethod
    local nSuccess
    nSuccess = 1
    if !(vartype(sStream)=="C".and.len(sStream)>0)
      nSuccess = -1
    else

      with this
        .cKey = iif(vartype(cKey)=="C",cKey,"")
        .nEncrMethod = iif(vartype(nEncrMethod)=="N",nEncrMethod,0)
        * <- Decryption code here

        * ->
      endwith

    endif

    return nSuccess
  endfunc

enddefine
 
Thanks to you, Darrell, for pursuing issues like these.

I've often encountered the "remove classes from memory?" problem, and similar file-locking problems based on SET PROCEDURE TO. But being simply pragmatic, I issue broad SET PROCEDURE TO, SET CLASSLIB TO, CANCEL, CLEAR ALL, CLEAR PROGRAM commands, and if they fail (which they sometimes do), I just exit and reload VFP. It would be nice to have better control!



- Bill

Get the best answers to your questions -- See FAQ481-4875.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top