-
Notifications
You must be signed in to change notification settings - Fork 4
methodsVsProperties
When writing a MATLAB class you can define the following:
- properties, including the dynamic variety
- methods
Dynamic methods allow the programmer to execute arbitrary code between the data stored in the object, and the user's request to get or set a property. The question arises: should the feature you are programming be a property or a method?
On the face of it, the main difference is that a property cannot take parameters but provides the convenience of letting you write:
x.property.subfield = someValue;
If you had written it as a method, you'd have to write:
data = x.getProperty();
data.subfield = someValue;
x.setProperty(data)
(assuming x is a handle class object)
MATLAB also lets you choose how you invoke a method. In the above example you could just as well have written for the first line:
data = getProperty(x);
This ability to call methods either way is a truly peculiar feature of Matlab. The only mainstream language with a somewhat similar (but actually quite different) flexibility appears to be JavaScript. So there is the related question, how should I invoke the method?
rajlabimagetools tries to interpret a statement like this,
x.method(parameters);
with a template like so:
subject.verb(modifiers)
Here are a few translations applying this template:
navigator.tryToGoToNextObj()
Navigator, try to go to the next object.
objectHandle.setData(newData, 'cy')
objectHandle, set the data for 'cy' to newData.
When we don't use object notation (dot notation) to call a method or a function:
method(x, parameters)
we interpret it as:
verb(object, modifiers)
Now the object is often also grammatically the verb's object, rather than the subject performing the action, and we think of these verbs as transitive. For example, if we plot(x)
, we plot what? x. Who does the plotting? You, or Matlab, or your computer, or whoever else you'd like to think is executing the function calls you request as a programmer. In such a construction the subject is implied rather than explicit.
When we consider properties, though there is no flexibility in how you get at them, there are two ways to interpret them. It could be:
entity.attribute
or
complexData.field
So survey.gender
is the gender column from some survey data but person.gender
tells you the gender of that person.
It is good practice to create clear separation between classes that are primarily containers for data (data structures) from classes that are primarily manipulators of data and other objects. There are very few data structures in rajlabimagetools. They include the ImageObject, the node graph, and the bits of data (such as ProcessedData) that go in the nodes. Most every other class represents a manipulator or actor.
Matlab's native data structures are pass-by-value, non-handle classes. On the other hand, manipulators or actors need to retain their identity even if some aspect of their state changes, so they must be programmed as handle classes.
Objects belonging to handle classes can reasonably be the subjects of sentences. When we say objectHandle.getData('cy')
we truly mean to ask the objectHandle to go fetch that data. Similarly, since these objects should not be thought of as data structures, the interpretation entity.attribute
is more appropriate than complexData.field
.
Data is best thought of as inanimate or at least not active. It rarely makes sense for it to be the subject of a sentence. That is why we have avoided use of syntax such as:
spotsData.getNumSpots()
Even though Matlab would allow us to make such a call. We prefer instead:
getNumSpots(spotsData)
A trickier question is whether we should
getNumSpots(spotsData)
or
spotsData.numSpots
Suppose we have defined a data structure class, SpotsData, that represents a collection of spots in an image. We want to give the user access to some computed value based on the spots data. For the sake of argument, let's say our users really want to know the center of mass of all the spots.
we could code:
getCenterOfMass(spotsData)
or create a dynamic property:
spotsData.centerOfMass
We would choose the method version rather than the property, because the Center of Mass can be computed from the existing publicly-available fields and methods of SpotsData. Therefore, a centerOfMass
field would appear to the user to be totally redundant information in the spotsData. Another hint that it would be a bad idea to use a property is that it would make no sense for the user to be able to set the centerOfMass
of SpotsData.
Consider a data structure that describes a blob of jello. Its only publicly accessible attributes are a height jello.height
and a width jello.width
. Let's say you press down on it with your palm and therefore directly reduce jello.height
. But now, jello.width
has increased. There is no way you could have calculated how much the width was going to change because you don't have access to the internals and composition of the jello block. Jello height and width are well-modeled as dynamic properties at this level of detail.
You could alternatively model the jello
without dynamic properties by making finer detail available. Suppose we now had publicly accessible attributes jello.elasticConstants
and jello.topPressure
. Adjusting one does not affect the other, and both the height and the width are computable from them.
The designer must choose what data the user wishes to model. In the first scenario we were just modeling the width and height. In the second, we were providing a lower-level model.