Gracias a todos. Conceptualmente estoy de acuerdo en que es mejor por norma definir los metodos en la clase que declara la propiedad. El problema se dio porque empezo a dar error un test unitario y de ahi empezamos a analizar que lo habia generado; entonces detectamos esta situación. Es mejor por norma que si hay un _access y un _assign se definan en la clase que declara la variable, pero en MSDN especifica que son metodos independientes y puede existir uno sin otro, no menciona ni controla que ese metodo no se defina en la subclase y funciona con esa definicion. Adjunto (y copio al pie por si no se puede descargar) dos PRG con el ejemplo que mencione (que no es el real sino uno creado para probar este caso); uno es EjemploMAL.prg y otro EjemploBIEN.prg que son simplemente el que da error y el que funciona bien, su unica diferencia es el orden de creacion de los objetos: primero persona y despues empleado no da error, primero empleado y despues persona si da error (lineas 5 y 6). Incluso ejecutando primero el que esta bien y despues el que esta mal funciona, a veces si primero se ejecuta el que esta mal y despues el que esta bien sigue dando error aun en el que esta bien. Mi deduccion por lo que investigue es que al crear un objeto persona se puede usar la funcion amembers() para acceder a la clase base y supongo (pero no pude encontrar ninguna referencia) que carga toda la estructura jerarquica de herencia. En el caso original nuestro devuelve 85 propiedades en la clase base y 89 en la implementada. Y como el _access tiene prevalencia sobre la variable creo que deja la referencia y cuando se crea el segundo objeto (ahora de la clase base) ya detecta que esta cargada la estructura, no vuelve a cargarla y toma esa referencia a un _access que no existe, porque el error es que /*no se encontro la propiedad variable_access*/. Y eso si creo que es un Bug ya que no deberia funcionar dependiendo del orden de creacion de los objetos. Comparti el caso para confirmarlo porque no encontramos documentacion, es un caso de deduccion personal y toda opinion aporta. Creo que sirve como norma de codificacion ....
Gracias a todos.

/Juan/

Ejemplo Bien

local loEmp, loPer, lnCantidad
dimension laPropiedades(1)

*!*     Orden de creacion de objetos
loPer = newobject(  'Persona' )
loEmp = newobject( 'Empleado' )
*!*     Fin de Orden de creacion de objetos

?loPer.Apellido
lnCantidad = Amembers( laPropiedades,loPer,0,"UG+" )
?lnCantidad

for i = 1 to lnCantidad
    lcPropiedad = "loPer."+ alltrim( laPropiedades[i] )
    if vartype( evaluate( lcPropiedad ) ) = "O"
        if pemstatus(&lcPropiedad,"release",5)
            lcEliminaReferencia = lcPropiedad + ".release"
            &lcEliminaReferencia
        endif
    endif
endfor

loPer.Apellido = 'GOMEZ'

?loPer.Apellido

loPer = null

loEmp = newobject( 'Empleado' )
?loEmp.Apellido
lnCantidad = Amembers( laPropiedades,loEmp,0,"UG+" )
?lnCantidad

lnCantidad = Amembers( laPropiedades,'Persona',0,"UG+" )
?lnCantidad

loEmp = null

return


define class Persona as Custom

    Apellido = ''
    Nombre = ''

*-----------------------------------------------------------------------------------------
    function Apellido_assign( tcVal as String) as Void
        this.Apellido = tcVal
    endfunc


enddefine

define class Empleado as Persona


    documento = 0

*-----------------------------------------------------------------------------------------
    function Apellido_access() as String
        return this.Apellido
    endfunc

enddefine



Ejemplo Mal

local loEmp, loPer, lnCantidad
dimension laPropiedades(1)

*!*     Orden de creacion de objetos
loEmp = newobject( 'Empleado' )
loPer = newobject(  'Persona' )
*!*     Fin de Orden de creacion de objetos

?loPer.Apellido
lnCantidad = Amembers( laPropiedades,loPer,0,"UG+" )
?lnCantidad

for i = 1 to lnCantidad
    lcPropiedad = "loPer."+ alltrim( laPropiedades[i] )
    if vartype( evaluate( lcPropiedad ) ) = "O"
        if pemstatus(&lcPropiedad,"release",5)
            lcEliminaReferencia = lcPropiedad + ".release"
            &lcEliminaReferencia
        endif
    endif
endfor

loPer.Apellido = 'GOMEZ'

?loPer.Apellido

loPer = null

loEmp = newobject( 'Empleado' )
?loEmp.Apellido
lnCantidad = Amembers( laPropiedades,loEmp,0,"UG+" )
?lnCantidad

lnCantidad = Amembers( laPropiedades,'Persona',0,"UG+" )
?lnCantidad

loEmp = null

return


define class Persona as Custom

    Apellido = ''
    Nombre = ''

*-----------------------------------------------------------------------------------------
    function Apellido_assign( tcVal as String) as Void
        this.Apellido = tcVal
    endfunc


enddefine

define class Empleado as Persona


    documento = 0

*-----------------------------------------------------------------------------------------
    function Apellido_access() as String
        return this.Apellido
    endfunc

enddefine



El 01/01/2015 11:25 p.m., César Pistiner escribió:

Buenas noches Juan

Yo estoy de acuerdo con Omar, acces y assign van juntos o simplemente usas uno u el otro, pero siempre dentro de la misma clase. De todas formas es interesante el comportamiento que mencionas de vfp. Si instancias una clase primero que la otra funcionan distinto? Eso si esta feo... Igual te repito nunca se me dio la necesidad de tener algo así, cuál es tu caso de uso?

Saludos,
César


El jue, ene 1, 2015 04:04 PM, Fernando D. Bozzo <[email protected] <mailto:[email protected]>> escribió:

    Omar tiene razón:

    Access y Assign conviene crearlos juntos y simplemente son usados
    por quienes lo necesiten.

    Saludos.-



    El 1 de enero de 2015, 19:58, Omar Bellio <[email protected]
    <mailto:[email protected]>> escribió:

        A ver si entendí bien:

        Cuando vos definís una clase con una propiedad, todo eso
        hereda hacia abajo, Empleado hereda de Persona, si vos ponés
        un método en Empleado, Persona no lo va a ver. Normalmente
        cuando pasa eso, se pone una interfaz (creo que se llama así)
        en la clase madre, es decir, definís el método y no le ponés
        código, queda abstracto para especializar en las subclases. De
        ese modo, el método siempre está, aunque no haga nada.

        Resumiendo para tu ejemplo: el método _Access tiene que estar
        en la clase madre, para que no te pase eso.

        Saludos.

        *De:*[email protected] <mailto:[email protected]>
        [mailto:[email protected] <mailto:[email protected]>] *En nombre
        de *Jose Paez
        *Enviado el:* miércoles, 31 de diciembre de 2014 07:59 p.m.
        *Para:* GUFA List Member
        *Asunto:* [GUFA] _Access y _Assign

        Hola Juan

        Yo he utilizado bastante estos métodos  en un framework que
        desarrolle hace mucho tiempo.

        Tendrás un ejemplo que puedas pasarnos (.prg o .vcx) para
        analizarlo.

        Saludos

        José Paez

        > Date: Wed, 31 Dec 2014 10:32:05 -0300
        > From: [email protected] <mailto:[email protected]>
        > To: [email protected] <mailto:[email protected]>
        > Subject: [GUFA] _Access y _Assign
        >
        > Descubrimos un problema con los metodos _Access y _Assign en
        herencia.
        > En una clase hay una propiedad y esta tiene definido el
        metodo _assign.
        > Otra clase hereda de esta y define para esa propiedad el
        metodo _access.
        > Pongo como ejemplo una clase Persona y otra Empleado que
        hereda de
        > Person. Se crea un objeto de cada clase. Si se crea primer
        la clase base
        > (persona) y despues la subclase (empleado) se puede acceder
        a la
        > propiedad de la primera (ejemplo Persona.Apellido). Si se
        crea primero
        > la subcase (empleado) y despues la base (persona) y se
        quiere acceder a
        > la propiedad que tiene el metodo _access en la subclase da
        error porque
        > no encuenta el metodo _access (al intentar Persona.Apellido
        da error
        > porque no encuentra apellido_access). Por lo que estuve
        investigando el
        > tema es que cuando crea un objeto levanta la estructura
        jerarquica de la
        > clase (a la que se puede acceder con la funcion amembers()
        consultando
        > por el objeto o cada clase en la jerarquia) y hace
        referencia a cada
        > propiedad si tiene algunos de los metodos (_access o
        _assign). No
        > encontre documentación que lo mencione, solo paso y lo
        confirme con un
        > pequeño ejemplo como el que describi (una clase persona con
        propiedades
        > apellido y nombre y una funcion apellido_assign y otra clase
        empleado
        > que hereda de persona con una propiedad mas cuil y el metodo
        > apellido_access). En la documentacion de microsoft menciona
        > explicitamente que se puede usar indistintamente _access o
        _assign, pero
        > nada habla de la herencia ¿alguien sabe algo de esto? Por lo
        que vimos
        > si se usa _access o _assign hay que crearlas en la misma
        definicion
        > donde esta la propiedad a menos que sea una clase abstracta
        y no se cree
        > ninguna instancia de la misma. No se si interesa pero para
        nosotros es
        > importante como norma de desarrollo.
        > Muchas gracias.
        >
        >


Attachment: ejemplobien.prg
Description: application/prg

Attachment: ejemplomal.prg
Description: application/prg

Responder a