4

After evolving my project code for months, I've finally hit a need to define a new class. Having to romp through my previous class definitions as a refresher of the conventions, I noticed that all constructors and property setters all have an output argument, even though nothing is assigned to it, e.g.:

function o = myConstructor( arg1, arg2, ... )
function o = set.SomeProperty( o, arg1 )

I've been looking through the documentation for upward of an hour without finding the explanation for this. It doesn't look like it depends on whether a function is defined in the class definition file or in its own separate m-file.

Can anyone please explain?

user36800
  • 2,019
  • 2
  • 19
  • 34

1 Answers1

7

The best place to start is the documentation "Comparison of Handle and Value Classes". From the very top:

A value class constructor returns an object that is associated with the variable to which it is assigned. If you reassign this variable, MATLAB® creates an independent copy of the original object. If you pass this variable to a function to modify it, the function must return the modified object as an output argument.

A handle class constructor returns a handle object that is a reference to the object created. You can assign the handle object to multiple variables or pass it to functions without causing MATLAB to make a copy of the original object. A function that modifies a handle object passed as an input argument does not need to return the object.

In other words, value classes need to return a modified object (which is a new object distinct from the original), while handle classes don't. The constructor of either class will always have to return an object, since it is actually constructing it.

Some good additional reading is "Which Kind of Class to Use", which links to a couple helpful examples of each type of class object. Looking at the DocPolynom value class example, you can see that property set methods have to return the modified object, while the dlnode handle class example only requires an output for its constructor. Note that you could still return an object from a handle class method (if desired), but it's not required.

Community
  • 1
  • 1
gnovice
  • 125,304
  • 15
  • 256
  • 359
  • 1
    Thank you, gnovice. All of my classes are derived from `handle` or its derivative `matlab.mixin.Copyable`. I'm in the midst of a wholesale code change throughout the project, but when it's ready to test, I will get rid of the output arguments in the property setters. According to the [documentation](http://www.mathworks.com/help/matlab/matlab_oop/property-set-methods.html), it is not required. – user36800 Jul 11 '18 at 21:44
  • 1
    @user36800: Glad to help. The only real use I can think of for keeping the outputs for a handle class would be to create chainable behavior for methods, like `doItMore(doItAgain(doIt(obj)));`. – gnovice Jul 11 '18 at 23:46
  • Yes. When a method doesn't return the object itself, I make it a habit to return the property that the caller is most likely to use. There's probably execution overhead; from googling, in the context of the called function, one can't tell whether an output argument has been requested at the caller level. In the called function, therefore, there is no way to avoid assignment to the output argument for the case where return value is not used. – user36800 Jul 12 '18 at 13:39
  • For objects of handle class, however, the overhead is probably quite small. Only a possible concern if used in inner loops of computationally intensive model implementations. The payoff is that when I do need to access the output argument, the code is more streamline, and it can be chained. – user36800 Jul 12 '18 at 13:39
  • @user36800: With regard to finding out how many outputs have been requested from a called function, I believe [`nargout`](https://www.mathworks.com/help/matlab/ref/nargout.html) should work properly when called from within a class method, although [there may be some ambiguity](https://www.mathworks.com/matlabcentral/answers/133518-unexpected-value-for-nargout-when-returning-a-class-struct). – gnovice Jul 12 '18 at 14:23
  • IIRC, the issue was determining which output arguments are used. Changing topics, your answer points to documentation about returning a method's parent object if it changes any of the object's properties, and if the class is a value class. Is there a ready example of how to return outputs in addition to the object itself? Classical Matlab requires concatenation of target variables on the LHS of the assignment ,e.g., `[x, ~, z]=myFunc(a,b)`. It gets opaque when one of the outputs is the object itself, which gets assigned behind the scenes. – user36800 Jul 12 '18 at 14:45
  • @user36800: It's a little unclear, but it sounds like you are asking how to deal with a method that both modifies an object it must return (i.e. a value class object), as well as returning additional arguments. You should just be able to output them as you describe (e.g. `[obj, data1, data2] = myMethod(obj);`). It would just be the necessary to ensure that the calling function handles the outputs properly. – gnovice Jul 13 '18 at 20:18
  • Yes, that's (sort of) my question, thanks. My confusion comes from the fact that I've been treating handle and value classes almost the same (I know they mean), with a simply removal of `< handle` if I wanted to switch. From the documentation on [Passing Value Objects](http://www.mathworks.com/help/matlab/matlab_oop/matlab-vs-other-oo-languages.html#bslvcxo-1), however, when a function modifies an object property, I must always *explicitly* overwrite the original object with the returned object. I assume that this also applies to methods that modify the object? – user36800 Jul 15 '18 at 13:50
  • If explicit overwriting of the original object is needed when a method modifies its own object, then the use of property set methods get very confusing. For a handle object, I just do `myObject.myProperty = NewValueForSetMethod`. I can't imagine what code pattern is needed for a value object. – user36800 Jul 15 '18 at 13:50