MATLAB Answers

How to call sub or superclass constructor when recursively creating objects

20 views (last 30 days)
Tom Clark
Tom Clark on 28 Aug 2016
Commented: Guillaume on 30 Aug 2016
Hi,
I'm writing a tree class. I'd like a superclass to contain generic construction / maintenance methods, then be able to subclass it for a range of different, more specific purposes.
Something like:
classdef SuperTree < handle
properties
BranchLocation
Parent
Children
end
methods
function obj = SuperTree(varargin)
% construct the the object
end
function subdivide(obj, limit_criterion)
% Lots of code that's difficult to maintain and
% shouldn't be overloaded in a subclass
if limit_criterion
% Create child branches
chld1 = SuperTree(args);
chld2 = SuperTree(args);
obj.Children = [chld1; chld2]
end
end
end
The problem is that if I create a subclass, then the subdivision method still makes a call to SuperTree() to construct its children.
Is there a way of getting (say) a handle to the constructor function of the current object? I don't want to be overloading the subdivide method for each of my subclasses. Something like this would be ideal:
function subdivide(obj, limit_criterion)
% Lots of code that's difficult to maintain and
% shouldn't be overloaded in a subclass
if limit_criterion
% Create child branches
chld1 = obj.Constructor(args);
chld2 = obj.Constructor(args);
obj.Children = [chld1; chld2]
end
At the moment I'm working around this with a small utility method, that I overload in each subclass. Working? Yes. Elegant? No. So I'd be interested in any 'proper' solutions.
Thanks!
Tom

  3 Comments

Guillaume
Guillaume on 29 Aug 2016
"At the moment I'm working around this with a small utility method, that I overload in each subclass. Working? Yes. Elegant? No"
Actually, that is the normal way of dealing with this. The other way, using reflection as in per isakson answer, I find inelegant.
per isakson
per isakson on 30 Aug 2016
@Guillaume, which problems do you see in using class(obj) in this context?
This "small utility method" does it contain expressions like chld=Tree(args);?
Guillaume
Guillaume on 30 Aug 2016
I don't see any problem in using class(obj). It works fine. It's probably because I come from C++ where reflection does not exist that I find it inelegant. It's probably irrational
If I understood correctly (and the way I'd do it), the small utility method is a one-liner method that is overloaded in each class and just call the class constructor:
classdef SuperTree < handle
%... props definition
methods
function obj = SuperTree(varargin)
% construct the the object
end
function subdivide(obj, limit_criterion)
% Lots of code that's difficult to maintain and
% shouldn't be overloaded in a subclass
if limit_criterion
% Create child branches
chld1 = NewMe(args);
chld2 = NewMe(args);
obj.Children = [chld1; chld2]
end
%small utility function to be overloaded in each subclass
function this = NewMe(args)
error('Must be overloaded by children');
this = SuperTree(args);
end
end
end
and child
classdef Child < SuperTree
%... props definition
methods
function obj = Child(varargin)
% construct the the object
end
function this = NewMe(args)
this = Child(args);
end
end
end

Sign in to comment.

Answers (1)

per isakson
per isakson on 28 Aug 2016
Edited: per isakson on 30 Aug 2016
I think, I understand and that it's doable. Replace
chld1 = obj.Constructor(args);
by
str = class( obj );
chld1 = feval( str, args );
And in the constructor of the subclass
obj@SuperTree( arguments )
Whether this is the proper way, I don't know.
&nbsp
ADDENDUM 2016-08-29 in response to the comment: "2. this will eliminate any possibility for code generation."
Would this allow code generation? Replace
chld1 = feval( str, args );
by
chld1 = TreeFactory( str, args );
where the simplest form of TreeFactory is an ordinary function
function tree = TreeFactory( str, args )
switch str
case 'oak', tree = Oak( args );
otherwise
end
end

  3 Comments

Tom Clark
Tom Clark on 28 Aug 2016
Thank you Per, that's definitely a significant step. It works, so I've upvoted, and I'll accept in a while if no other answers come through.
However, I do have two concerns with this strategy: 1. that feval() is likely to be quite slow (troublesome for cases where a tree is repeatedly built) and 2. this will eliminate any possibility for code generation.
Admittedly, I didn't put those considerations into the question!
Any further thoughts appreciated :)
per isakson
per isakson on 28 Aug 2016
There has been complains regarding the performance of MATLAB OOP. However, its improving. I've learned to avoid solutions with thousands of simple objects.
"feval() is likely to be quite slow" &nbsp Based on some simple tests (R2016a) I don't think so. (That is, it's not slow compared to other ways to create objects in Matlab.)
"will eliminate any possibility for code generation" &nbsp Yes.
Given the superclass, handle, I cannot think of any other approach. Or maybe, see Clone Handle Object - using MATLAB OOP by Bobby Nedelkovski

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!