How to call sub or superclass constructor when recursively creating objects

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 件のコメント

Guillaume
Guillaume 2016 年 8 月 29 日
"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 2016 年 8 月 30 日
@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);?
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

サインインしてコメントする。

回答 (1 件)

per isakson
per isakson 2016 年 8 月 28 日
編集済み: per isakson 2016 年 8 月 30 日
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 件のコメント

Tom Clark
Tom Clark 2016 年 8 月 28 日
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 2016 年 8 月 28 日
編集済み: per isakson 2016 年 8 月 28 日
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
per isakson
per isakson 2016 年 8 月 29 日
I added an alternative to feval to the answer.

サインインしてコメントする。

カテゴリ

ヘルプ センター および File ExchangeConstruct and Work with Object Arrays についてさらに検索

質問済み:

2016 年 8 月 28 日

コメント済み:

2016 年 8 月 30 日

Community Treasure Hunt

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

Start Hunting!

Translated by