Suppose I have a two classes, parent and child. Parent holds an array of instances of child. Child has several (computed) properties (to catch changes). How do I tell the parent class that one of the child’s value has changed and it should do something accordingly?
Up to now, I have a class constructor for the child class (type of the parent class). When initiating a new child instance on the parent instance, I pass “self” to the constructor. The parent has a (public… not so nice.) method “childValueChanged” that is called from within the child instance.
Warning, you are building a circular reference here: the parent keep a reference to the child which keep a reference to the parent
I’d go this way:
define one (or more) Private method(s) on parent to get called when one ore more child properties change.
define one or more Events in child to be fired when something changes.
pass a reference to parent on child constructor (as you already do) BUT don’t retain it in a child property.
on child constructor, wire the child events to the parent’s purposely created methods using AddHandler Child.Event, WeakAddressOf Parent.MethodHandler. Since you can wire many Events instances to the same method you will be still able to see which child sent the event, that is the first parameter of the parent event handler method.
There are some nice design patterns for this sort of thing.
AddHandler isn’t one.
Observer is a nice pattern for this and can be reused throughout an app and doesn’t require AddHandler.
AddHandler is great for some things but when over used can be the source of modern spaghetti code.
And you can lift almost all the required code right out of the Examples Projects > Design Patterns > Observer example we already supply (you might need to alter it for your purposes) but the idea is very straight forward
What Massimo is suggesting is is to use addhandler instead of the interface to set up the pattern.
AddHandler is great for some tasks - but I see it being used far too frequently and some really interesting bug reports as a result with some projects that would be better off ignoring AddHandler ever existed.
Like Introspection 99.9% of the time you dont need it and there are better alternatives. But when you do it IS the only way to do something.
I agree with Norman that AddHandler should be used with a grain of salt. It can sort out in very complicate to debug code sometimes.
Still my example is very efficient, however , but if a well tested OOP design pattern could be implemented, I agree it would be better. Even if it’s sometimes more complicated code.
Btw. this kind of mechanism of delegation is pretty common in Cocoa/Obj-C but yet I have to say it’s much better supported and doesn’t generally produce spaghetti code.
Though one question: My set up is just the other way around compared to the example. I do have one object that should observe multiple others. Wouldn’t AddHandler suit better? How would I need to change the design pattern then?
Edit: I mean I’d need to keep a reference to all “subjects” / “observed” children in the parent object - thus again creating a reference…
I know this feeling too. You want a method used only by a specific class but it feels ‘wrong’ to have it public. The only way to hide away such methods is through inheritance or passing delegates or addhandler. Or you can just leave it public. I see this even in Apples docs, such as NSWindow has 5 public methods with a description of “never invoke this method directly”. It’s not so bad to leave it public, you have to do that with observer anyways.
I think your original setup isn’t that bad. It IS the observer pattern, just not in a generalized fashion. The child keeps a reference to the parent that’s observing it and calls those methods on the parent when it’s values change. Very direct, but also very specific; the linkage only works between those 2 classes. If you need more flexibility then use a full bodied pattern.
If you stay with your original setup you might try using name prefixes and/or an interface to group things. So all the public methods on the parent for callback would have a singular, non-generic prefix. This makes them stand out a bit more and keeps them together in the alphabetically sorted navigator.
Well, one could hide them from AutoComplete using attributes… If only there was a scope for methods/properties for classes that hold a reference to it (or similar). Or have a whitelist for the private scope anyway…
Ha, that somehow makes me feel clever But indeed, it’s just between those two classes… I am not sure it’s worth to implement it in a more general fashion then - I’d need to keep a reference of the parent anyway (be it in the child or a third class) to notify it when a change happened… right?