Accessing values of properties in ancestors
If you are using ancestors, there are times when you want to access the value of an inherited property.
Here is a simplistic example:
-- Script 1 property ancestor
on new(me) ancestor = script(2).new() put me.pInheritedProperty return me end
-- Script 2 property ancestor
on new(me) ancestor = script(3).new() return me end
-- Script 3 property pInheritedProperty
on new(me) pInheritedProperty = #success return me end
-- In the Message window:
put script(1).new() -- #success -- <offspring "" 1 722ea90>
The instance of script 1 inherits properties from its ancestor, and from its ancestor's ancestor, and so on. The syntax 'me. pInheritedProperty' will return the value of a pInheritedProperty property in the 'me' instance itself, if one exists. If not, Director will look in each instance in the ancestor hierarchy in turn, until it finds a #pInheritedProperty property. If no ancestor possesses such a property, this will provoke a Script Error.
Alternative Syntaxes
The syntax me[#pInheritedProperty] and me.getaProp(#pInheritedProperty) are not equivalent when you are working with instances which have ancestors.
put me.getaProp(#pInheritedProperty) -- Looks for pInheritedProperty at the inheritor's end of -- the ancestor hierarchy. Will return <Void> if the 'me' -- instance does not have a pInheritedProperty, even if -- such a property exists in an intervening ancestor.
put me[#pInheritedProperty] -- Looks for pInheritedProperty at the ancestor's end of -- the ancestor hierarchy. Will return <Void> if the final -- ancestor does not have a pInheritedProperty, even if -- such a property exists in an intervening ancestor.
Example
-- Script 1 property ancestor property pProperty
on new(me) ancestor = script(2).new() pProperty = #script1
put me.pProperty, "me.pProperty" put me.getaProp(#pProperty), "me.getaProp(pProperty)" put me[#pProperty], "me[#pProperty]" put me.getaProp(#pAncestorOnly), "me.getaProp(pAncestorOnly)"
return me end
-- Script 2 property ancestor property pProperty property pAncestorOnly
on new(me) ancestor = script(3).new()
pProperty = #script2 pAncestorOnly = #inaccessible
return me end
-- Script 3 property pProperty
on new(me) pProperty = #script3 return me end
-- In the Message window: put script(1).new() -- #script1 "me.pProperty" -- #script1 "me.getaProp(pProperty)" -- #script3 "me[#pProperty]" -- <Void> "me.getaProp(pAncestorOnly)" -- <offspring "" 1 7093e80>
Bullet-proof Access to Inherited Properties
Here is a handler that will act like me.pProperty, but which will not cause a script error if no instance in the ancestor chain possesses a property named pProperty. Instead, it will return <Void>.
on GetProperty(anObject, aProperty) repeat while TRUE vValue = anObject.getaProp(aProperty) if voidP(vValue) then
anObject = anObject.getaProp(#ancestor) -- climb the chain if ilk(anObject) <> #instance then return VOID end if
else return vValue end if end repeat end GetProperty
The handler above gives you no way of telling whether the given property exists, but has a value of <Void>, or whether no instance in the ancestor hierarchy possesses a property with the given property name. The handler below will return a value from 0 to n, where n is the number of instances in the ancestor hierarchy. The return value will correspond to the level in the hierarchy where the given property is first encountered, or 0 if none of the instances in the hierarchy possess a property with the given name.
on PropertyExists(anObject, aProperty) vIndex = 1
repeat while TRUE if voidP(anObject.getaProp(aProperty)) then anObject = anObject.getaProp(#ancestor) -- climb the chain if ilk(anObject) <> #instance then return FALSE end if
else return vIndex end if
vIndex = vIndex + 1 -- position in the chain end repeat end PropertyExists