On Fri, 19 Feb 2010, Maurilio Longo wrote:

Hi Maurilio,

> you said that harbour cannot differentiate an iVar named ::atStart from a
> method with the same name.

It's standard Clipper behavior.
This code:
   x := obj:msg()
gives exactly the same PCODE as
   x := obj:msg

Clipper does not make any difference here and in both cases sends
message 'msg' to 'obj' object.
Only assign operation is compiled in different way and code like:
   obj:msg := x
gives exactly the same PCODE as:
   obj:_msg( x )
so Clipper send message '_msg' to object 'obj' with assigned value passed
as 1-st parameter.
Harbour is fully Clipper compatible here.

> Now, this causes problems with xpp compatibility where such a possibility
> exists, but, in the beginning, we could say that when I call
> 
> ::Start( "mysymbol" )
> 
> I'm probably not going to depend on a method ::atStart which can exist only in
> sublasses of TThread  which I would start with a
> 
> oMyT := oMyClass():New():Start()
> 
> So, question is: is there a way to know if a class implements a method? In
> which case we could run the ::atStart() method which is better than nothing, 
> IMHO.

There is no clean way to detect it because in both cases these are
messages only so we can only use some hacks, i.e. check default function
attached to given message. If it's one of standard functions used to access
instance variables then we can decide it's variable. Anyhow such code
stops to work when someone uses ACCESS/ASSIGN/SETGET messages as wrapper
to instance variables in subclasses. In such case we will detect it as
normal messages.

> I see in changelog a
> __objHasMsgAssigned( object, "msgName" )
> and then a __objHasMsg and a __objHasData, don't distinguish methods from 
> ivars?

__objHasMsg() checks if object understands message (it was declared
in class of given object or one of its ancestors)

__objHasMsgAssigned() checks if object understands message and this
message is not redirected to the default function used for method
declared as VIRTUAL or DEFERRED.

__objHasData() is one object/class functions defined in src/rtl/objfunc.prg
which from the beginning only have been confusing users suggesting that
they are making sth different then they really can :-(

In fact they are using some tricks only and the returned information
can be completely different then expected value in some cases.
__objHasData( <obj>, <msg> ) returns .T. if object understands two
messages: <msg> and also "_" + <msg>.

It the context you are asking for it does not return correct result.
It simply always return .T. for TTHREAD class and its all subclasses
because they inherit atStart and _atStart messages used for instance
variable atStart in base class.

The functionality you are asking for can be implemented as:

   #include "hboo.ch"

   function __objHasIVar( obj, cMsg )
      local aMessages, nPos
      aMessages := obj:classSel( ,, .T. )
      nPos := hb_ascan( aMessages, cMsg,,, .T. )
      if nPos != 0
         return aMessages[ nPos, HB_OO_DATA_TYPE ] == HB_OO_MSG_DATA
      endif
   return .F.

If you plan to use it then I can implement it directly in C so it will
be much more efficient then above .prg code which uses array with all
messages created by :classSel().

Or I can add function:

   __objMsgType( <obj>, <cMsg> | <sMsg> ) -> <nType>

so above __objHasIVar() can be implemented as:

   function __objHasIVar( obj, msg )
   retrun __objMsgType( obj, msg ) == HB_OO_MSG_DATA

> PS. If it were possibile to add this xpp extension it would be a good thing :)

I planed to add it as optional extension to core code but now we are
removing HB_COMPAT_XPP so I'll have to rethink it.

> I do understand though that it could require too much work to be considered a
> priority.

It's not very complicated.
In fact it can be done even quite simply using compile time macro so
this code can be enabled optionally.
The real problem is rather Clipper compatibility with code using explicitly
assign messaged with "_" prefix or not strictly respecting difference
between method and instance variables, i.e.:

   o := errorNew()
   ? o:cargo
   ? o:cargo()
   o:_cargo( "test" )
   ? o:cargo
   ? o:cargo()
   o:cargo := "assign"
   ? o:cargo
   ? o:cargo()

is valid Clipper code and such extension will interact with it.

best regards,
Przemek
_______________________________________________
Harbour mailing list (attachment size limit: 40KB)
[email protected]
http://lists.harbour-project.org/mailman/listinfo/harbour

Reply via email to