MATLAB Answers

Cedric Wannaz
0

Should I (and how to) avoid "forests" of listeners in nested OOP structure.

Asked by Cedric Wannaz
on 18 Dec 2017
Latest activity Edited by Cedric Wannaz
on 19 Dec 2017
Dear all,
System < handle, with properties System.grids and System.result
Grid < handle, with property Grid.layers
Layer < handle, with property Layer.gridCells
GridCell < handle, with property GridCell.area
where each class implements a property that is a cell array of objects of the class "below", i.e. System.grids={Grid obj #1,..}, Grid.layers={Layer obj #1,..} and Layer.gridCells={GridCell obj #1,..}. Property System.result is built/computed for a specific set of grids (and hence layers and grid cells). Its value must therefore be updated each time a grid or one the grids' layer or one of the layers' cell is updated (e.g. the area). EDIT 1 - If:
gc = system.grids{2}.layers{10}.gridCells{15200} ;
the following:
gc.area = 147 ;
should trigger an update of system.result.
In a less nested context, e.g. if updating a grid would be done through a basic set access to System.grids such as:
system.grids{3} = newGrid ;
I could manage triggering the update of result through a setter for the grids property. In a little more nested context, e.g. if layers can be updated without replacing Grid objects, through:
system.grids{3}.layers{1} = newLayer ;
I could set the layers property of Grid observable:
classdef Grid < handle
properties( SetObservable = true )
layers
end
..
an add listeners to the System object bound to each grid layers property and to the 'PostSet' event. Or better, I can define an event 'updated' in each class Grid, Layer, and GridCell, that would back-propagated to the System object through a chain of listeners: EDIT 2017/12/19 @ 19:30 UTC, e.g.:
classdef Grid < Cascadable
properties
layers
end
methods
function obj = Grid()
obj = obj@Cascadable() ;
end
function addLayer( obj, layer )
obj.layers{end+1} = layer ;
addlistener( layer, 'updated', ...
@(src, evnt) eventHandler_updated( obj, src, evnt )) ;
obj.eventHandler_updated() ;
end
end
end
with
classdef Cascadable < handle
events
updated
end
methods
function obj = Cascadable()
end
function eventHandler_updated( obj, varargin )
fprintf( '%s updated\n', class( obj )) ;
obj.notify( 'updated' ) ;
end
end
end
and an event handler in System that does a little more work, e.g. recomputing result.
While this last approach seems to be "clean enough", it requires adding setters that call NOTIFY for all relevant properties in each class, or overloading SUBSASGN for that purpose, or defining 'PostSet' listeners for all relevant properties of "self" (just for avoiding implementing a lot a setters and instead defining a single event handling method for all properties). This seems to be cumbersome and to defeat the purpose of events/listeners.
Is there a cleaner way? Did I miss an important mechanism, like a 'CascadedPostSet' event?
Cheers,
Cedric

  0 Comments

Sign in to comment.

0 Answers