Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Child object accessing property on parent object?
Message
 
À
18/08/2009 00:43:18
Information générale
Forum:
Visual FoxPro
Catégorie:
Programmation Orientée Object
Versions des environnements
Visual FoxPro:
VFP 9 SP2
Database:
Visual FoxPro
Divers
Thread ID:
01418582
Message ID:
01418609
Vues:
79
>I have an object (oParent), which has a property named oChild. Once oChild is instantiated, it needs to read some properties from the parent to do his work.

That would be a perfect usage for a delegate, if VFP would support them. ;-)

>Any other ideas?

This really depends on how you want to approach this...

The easiest way is to give oChild a reference to the parent and then access properties directly. It's also the fastest approach at runtime. The biggest technical issue is that you must remove the reference from oChild before you attempt to release either oChild or oParent. From a conceptional POV this approach is the worst one as it tightly couples the two objects. oChild has access to every property and method of oParent. While you can limit the code to access only the ones you actually need, you still have a problem when you later refactor the code. Even with a comment somewhere listing the properties you are allowed to access, there's nothing that guarantees this. A few years later you or even another developer won't believe the comment anymore. So you would need to review the existing code to find the actual dependencies between oChild and oParent.

You could isolate these dependencies into template methods. You would still have a oParent reference in oChild, but the code would be more isolated. if you need to access cName in oParent, you could add a cName property to oChild containing "cName". Also add a method DoGetName. This method would look like this:
Assert Vartype(This.oParent) == "O"
Return GetPem(This.oParent, This.cName)
This makes the knowledge about the parent interface configurable and provides a single method to override when providing a different property name isn't sufficient. You still have a dependency that is not as explicitly spelled out as it could be, but is much better than just using the object directly.

Another approach would be to use event binding. oChild provides a method to update properties with the current values. oParent binds to this method and provides the most recent version every time oChild accesses the cName property:
ox = CreateObject("CParent")
ox.ShowChild()

Define Class CParent as Custom
	oChild = null
  Procedure Init
		This.oChild = CreateObject("CChild")
		BindEvent(This.oChild,"UpdateName",This,"UpdateName")
	EndProc
	Procedure UpdateName
		This.oChild.cName = "Parent"
	EndProc 
	Procedure ShowChild()
		This.oChild.Show()
	EndProc
EndDefine 
 
Define Class CChild as Custom
	cName = "Child"
	Procedure cName_Access
		This.UpdateName()
	Return This.cName
	Procedure Show
		MessageBox(This.cName)
	EndProc 
	Procedure UpdateName
EndDefine
In a similar manner you could provide a method that fills a parameter object with the value for cName.
ox = CreateObject("CParent")
ox.ShowChild()

Define Class CParent as Custom
	oChild = null
  Procedure Init
		This.oChild = CreateObject("CChild")
		BindEvent(This.oChild,"DoGetName",This,"DoGetName")
	EndProc
	Procedure DoGetName(toData)
		toData.cName = "Parent"
	EndProc 
	Procedure ShowChild()
		This.oChild.Show()
	EndProc
EndDefine 
 
Define Class CChild as Custom
	cName = "Child"
	Procedure cName_Access
		Local loData
		loData = CreateObject("Empty")
		AddProperty(loData, "cName", NULL)
		This.DoGetName(m.loData)
	Return m.loData.cName
	Procedure Show
		MessageBox(This.cName)
	EndProc 
	Procedure DoGetName(toData)
		If IsNull(toData.cName)
			toData.cName = This.cName
		EndIf 
	EndProc 
EndDefine
Both approaches suffer from the additional complexity that BINDEVENTS() requires. For one, the protocol needs to be more complex in order to make this work. You either have to push updates from the parent to the client, or use additional objects to provide data. This is purely a technical limitation, because you can't bind to a method and have the return value being used by the caller. Even when the method in oParent is executed after oChild, the return value is always the one returned by the implementation in oChild. BindEvent is also more likely to cause bugs. When viewing the child class it's not all obvious that the value of the property changes when you access it. In the debugger this very difficult to trace though.

Another approach would be to create your own Delegate class. You could create a class that stores a reference in one property and a method name in another. The Invoke() method would use macro substitution to call the specified method in the specified object with the parameters passed to Invoke. In oParent you would create a delegate with the reference to the parent object and a method that returns one or multiple of these values. Pass this delegate object to the Init event of the Child class and store it in a properties. Whenever you need one of the values, call the Invoke method of the delegate. If necessary, use more than one delegate.Much like

Yet another approach uses a data provider object. Define a class that has one method for every property oChild needs to access. Create a subclass That stores a reference to the parent object and accesses the parent directly. In the parent class instantiate the DataProvider class specific for the parent and pass it to the child object. In the child object access the methods defined in the abstract data provider class. The advantage here is that any communication between the two obejcts is clearly channeled and everything that child needs is explicitly defined. The drawback is that you need to define another class. Data Provider wouldn't be as flexible as delegates, but are easier to maintain, at least in VFP.
--
Christof
Précédent
Suivant
Répondre
Fil
Voir

Click here to load this message in the networking platform