classdef Dog
methods
function bark(obj, text)
disp(text)
end
end
end
Suppose d = Dog(). Is there a way to make d("woof") be same as d.bark("woof")? Can the behavior of d() be changed in any other way?
In Python, that's overloading __call__.
subsref controls () behavior.
d(x) passes x to subsref, wrapped inside a struct.
Unpack as x.subs{1} and do anything, including returning an output.
subsref also controls {} and .; redirect these to its native implementation.
MATLAB recommends a mixin class, but that seems overkill.
Thanks to #CrisLuengo for the pointers. If anyone has more info, feel free to share.
classdef Dog
methods
function bark(obj, text)
disp(text)
end
function varargout = subsref(obj, x)
if x(1).type == "()" && length(x) == 1 && ~isempty(x.subs)
[varargout{1:nargout}] = obj.bark(x.subs{1});
else
[varargout{1:nargout}] = builtin('subsref', obj, x);
end
end
end
end
Related
I have some code from a collegue, and I want to add caching to one of the class methods without chancing the original code. I think I should simply overload that function, and call a memoized version of the superclass function. An example:
A.m
classdef A < handle
methods
function res = foo(obj, arg)
disp('class A')
res = arg; % expensive calculation
end
end
end
B.m
classdef B < A
methods
function obj = B()
fn = #foo#A;
obj.foo_m = memoize(fn);
end
function res = foo(obj, arg)
disp('class B')
obj.foo_m(arg)
end
end
end
Now it complains about a an invalid operator in line:
fn = #foo#A;
Furthermore I have the feeling that this might be an issue also: https://stackoverflow.com/a/21413098/1768422
How to solve this in an elegant/transparant way?
Assume we have a Matlab class called MyClas, as below,
classdef MyClass
properties
Value
end
methods
function foo(input1, input2)
...
end
end
end
What I am looking for is having MyClass.anyThing(inputValue), where anyThing and inputValue are arbitrary strings and anyThing is not a defined method in MyClass, passes anyThing and inputValue as two strings to my foo function.
In other words, I want to be able to handle undefined methods by passing their name and inputs to a function/method as strings.
I am having a hard time to elaborate on my issue since I don't know if there is any technical term for what I am trying to pull off here. Yet, I managed to find this link from math works, which just customizes indexing operations and does not exactly address my issue.
You can emulate this by hacking in an implementation of subsref. Like this:
classdef MethodRedirector
methods
function varargout = subsref(obj, S)
if numel(S) == 2 && strcmp(S(1).type, '.') && ...
strcmp(S(2).type, '()')
% Looks like obj.method(args)
fprintf('In method invocation to: %s with args:\n', S(1).subs);
celldisp(S(2).subs);
else
[varargout{1:nargout}] = builtin('subsref', obj, S);
end
end
end
end
The restriction is that callers must use the obj.method(args...) syntax, and cannot use the (usually equivalent) method(obj, args...) syntax.
Here's how that looks in practice:
>> mr = MethodRedirector; mr.someMethod(1, '2', magic(3))
In method invocation to: someMethod with args:
ans{1} =
1
ans{2} =
2
ans{3} =
8 1 6
3 5 7
4 9 2
Matlab does not allow to define different methods to define multiple constructors with different list of parameters, for instance this will not work:
classdef MyClass
methods
function [this] = MyClass()
% public constructor
...
end
end
methods (Access = private)
function [this] = MyClass(i)
% private constructor
...
end
end
end
But, as illustrated in above example, it is sometimes useful to have private constructors with particular syntax that cannot be called from public interface.
How would you best handle this situation where you need to define both public and private constructors ?
Checking call stack ???
classdef MyClass
methods
function [this] = MyClass(i)
if (nargin == 0)
% public constructor
...
else
% private constructor
checkCalledFromMyClass();
...
end
end
end
methods(Static=true, Access=Private)
function [] = checkCalledFromMyClass()
... here throw an error if the call stack does not contain reference to `MyClass` methods ...
end
end
end
Define a helper base class ???
% Helper class
classdef MyClassBase
methods (Access = ?MyClass)
function MyClassBase(i)
end
end
end
% Real class
classdef MyClass < MyClassBase
methods
function [this] = MyClass()
this = this#MyClassBase();
end
end
methods (Static)
function [obj] = BuildSpecial()
obj = MyClassBase(42); %%% NB: Here returned object is not of the correct type :( ...
end
end
end
Other solution ???
One sneaky trick that I've used to try and work around this limitation is to use another 'tag' class that can only be constructed by MyClass, and then use that to work out which constructor variant you need. Here's a simple sketch:
classdef MyClass
properties
Info
end
methods
function o = MyClass(varargin)
if nargin == 2 && ...
isa(varargin{1}, 'MyTag') && ...
isnumeric(varargin{2}) && ...
isscalar(varargin{2})
o.Info = sprintf('Private constructor tag: %d', varargin{2});
else
o.Info = sprintf('Public constructor with %d args.', nargin);
end
end
end
methods (Static)
function o = build()
% Call the 'private' constructor
o = MyClass(MyTag(), 3);
end
end
end
And
classdef MyTag
methods (Access = ?MyClass)
function o = MyTag()
end
end
end
Note the Access = ?MyClass specifier which means that only MyClass can build instances of MyTag. There's more about using that sort of method attribute in the doc: http://www.mathworks.com/help/matlab/matlab_oop/method-attributes.html
You can have a constructor that accepts multiple syntaxes by taking advantage of varargin:
classdef MyClass
methods (Access = public)
function obj = MyClass(varargin)
% Do whatever you want with varargin
end
end
end
You might, more typically, have some inputs that are required for all syntaxes, and then some optional inputs as well:
classdef MyClass
methods (Access = public)
function obj = MyClass(reqInput1, reqInput2, varargin)
% Do whatever you want with varargin
end
end
end
If you want to have even more control over how things are constructed, I would have a constructor and then also have some public static methods that called the constructor.
For example, let's say I wanted to be able to construct an object either by supplying parameters directly, or by supplying the name of a config file containing parameters:
classdef MyClass
methods (Access = public)
function obj = MyClass(reqInput1, reqInput2, varargin)
% Do whatever you want with varargin
end
end
methods (Static, Access = public)
function obj = fromFile(filename)
myparams = readmyconfigfile(filename);
obj = MyClass(myparams.reqInput1, myparams.reqInput2, ...);
end
end
end
Then you can create an object either with o = MyClass(inputs) or o = MyClass.fromFile(filename).
If you wanted to allow people to construct only from a config file, you could then make the constructor private. And you could add additional public static methods if you wanted to call the constructor in other ways.
In any case, the main point is that the idiomatic way to have a constructor that accepts multiple syntaxes is to take advantage of varargin.
I'd be tempted to go for a modification on your 1st option, but to modify the constructor to have an undocumented "mode" rather than just any input arg.
In the example below I gave that name **private** but you could have anything you want that the end users are unlikely to stumble across....
To be doubly sure you could still check the stack.
function [this] = MyClass(i)
if (nargin == 0)
% public constructor
else
% private constructor
if ischar ( i ) && strcmp ( i, '**private**' )
this.checkCalledFromMyClass();
else
error ( 'MyClass:Consturctor', 'Error calling MyClass' );
end
end
end
end
I am trying to run an OOP program in octave originally written for Matlab. I am not able to get most of the part right but not able to call methods.
Here's the sample code.
obj = Motor('SamplePeriod', 1/256, 'Beta');
methods(obj)
Methods for class Motor:
Motor Update
obj.Update();
error: invalid index for class
I tried reading the manual, couldn't get the instruction. Also there aren't any samples online as well.
As described here, you need to use the alternate way to call your method:
m = motor(...)
p = power(m, ...)
In your case that would be
Update(obj)
As mentioned by #Daniel
You can still call a method of a class using obj.Update() syntax, but you need to implement a special method in your class:
function varargout = subsref (obj, idx)
persistent __method__ method4field typeNotImplemented
if isempty(__method__)
__method__ = struct();
__method__.Update = #(o,varargin) Update (o, varargin{:});
# Error strings
method4field = "Class #s has no field #s. Use #s() for the method.";
typeNotImplemented = "#s no implemented for class #s.";
end
method = idx(1).subs;
if ~isfield(__method__, method)
error('Unknown method #s.',method);
else
fhandle = __method__.(method);
end
if strcmp (idx(2).type, '()')
args = idx(2).subs;
if isempty(args)
out = fhandle (obj);
else
out = fhandle (obj, args{:});
end
varargout{1} = out;
end
endfunction
More details can be found inside geometry package, look into inst/io/#svg folder.
I have the following class in MATALB.
classdef MyClass
properties
a;
end
methods
function foo(obj)
obj.a = 1;
end
end
end
Now, I do this.
mc = MyClass;
mc.foo();
Now we have this.
mc.a == []
This is something I don't understand. I was expecting
mc.a == [1]
Why hasn't the function foo changed the state of the object?
I am sorry if this is a very basic question. I am used to languages like Java and C#, where the semantics is clearly according to what I'm expecting.
I've discovered that if I do the following, it works are expected.
classdef MyClass < handle
But how to get the desired behavior with a value class in MATLAB (i.e. not a handle class)?
Since a value class is passed by value, not by reference, you need foo to return the updated object:
classdef MyClass
properties
a;
end
methods
function obj = foo(obj)
obj.a = 1;
end
end
end
Then
mc = MyClass;
mc = mc.foo();
This is why I only use handle classes.