MATLAB Answers

Calling superclass method outside of redefined method

조회 수: 49(최근 30일)
I have an "DataAnalyzer" classdef that has a method that slowly computes exact solutions to certain queries.
classdef DataAnalyzer < HandleCompatibleSuperClass
methods
function obj = DataAnalyzer(dat,varargin)
obj = obj@HandleCompatibleSuperClass(varargin{:})
% lengthy constructor using dat with immutable properties
end
y_results = analyze(obj,x_queries) % slow analysis method
% lots of other user methods to analyze data
end
end
For debugging, we can get good enough results with a DataInterpolator, that provides all the same methods EXCEPT redefines the analyze method.
classdef DataInterpolator < DataAnalyzer
properties(SetAccess=immutable)
DomainX
RangeY
end
methods
function obj = DataInterpolator(x_domain,dat,varargin)
obj = obj@DataAnalyzer(dat,varargin{:});
obj.DomainX = x_domain;
obj.RangeY = analyze@DataAnalyzer(obj,x_domain);
% ^ Can't do this!
end
function y_results = analyze(obj,x_queries)
y_results = interp1(obj.DomainX,obj.RangeY,x_queries,'linear');
end
% all those other useful methods to analyze data
end
end
Subclass methods can call superclass methods if both methods have the same name.
I realize that I could do something like this...
classdef DataInterpolator < DataAnalyzer
properties(SetAccess=immutable)
DomainX
RangeY
end
methods
function obj = DataInterpolator(x_domain,dat,varargin)
obj = obj@DataAnalyzer(dat,varargin{:});
% Create a temp object, but time is a penalty.
temp_obj = DataAnalyzer(dat,varargin{:});
obj.DomainX = x_domain;
obj.DomainY = analyze(temp_obj,x_domain);
end
function y_results = analyze(obj,x_queries)
y_results = interp1(obj.DomainX,obj.RangeY,x_queries,'linear');
end
% all those other useful methods to analyze data
end
end
But that feels like a really ugly hack, even for debug. Worse, I lose the performance benefits of constructing obj essentially twice.
Is there a smarter way to accomplish what I'd like to do here?

채택된 답변

Jacob Lynch August
Jacob Lynch August 16 Feb 2021
편집: Jacob Lynch August 16 Feb 2021
I went back to the author and brought up these techniques. He agrees that the level of hackery is unforuntate, but this is what we agreed to:
  1. An analyze_protected_static method was added to let us access any superclass analyze method.
  2. The constructor of Interpolator calls that static method of the superclass to get the instance data.
classdef DataAnalyzer < HandleCompatibleSuperClass
methods
function obj = DataAnalyzer(dat,varargin)
obj = obj@HandleCompatibleSuperClass(varargin{:})
% ... lengthy constructor using dat to set immutable properties.
end
% This method is just a wrapper for the protected, static method.
y_results = analyze(obj,x_queries)
% ... lots of other user methods to analyze data
end
methods(Static,Access=protected)
% The true, slow analysis method.
y_results = analyze_protected_static(obj,x_queries)
end
end
Then the Interpolator subclass just constructs the domain data from the static method.
classdef DataInterpolator < DataAnalyzer
properties(SetAccess=immutable,GetAccess=private)
DomainX (:,1)
RangeY (:,:)
end
methods
function obj = DataInterpolator(x_domain,dat,varargin)
% Construct object
obj = obj@DataAnalyzer(dat,varargin{:});
obj.DomainX = x_domain;
obj.RangeY = DataAnalyzer.analyze_protected_static(obj,obj.DomainX);
end
function y_results = analyze(obj,x_queries)
% No if cases; YAY!
y_results = interp1(obj.DomainX,obj.RangeY,x_queries,'linear',nan);
end
end
end
Thank you for all your advice. It helped when discussing this with the author. It's unfortunate that we'll have to redistribute the pcode to other members that are using these methods.

추가 답변(2개)

Matt J
Matt J 15 Feb 2021
편집: Matt J 15 Feb 2021
Why do you have to do it through inheritance? Couldn't you pass a function handle to the analyze() method that you want as a constructor argument?
classdef DataAnalyzer < HandleCompatibleSuperClass
properties(SetAccess=immutable)
DomainX
RangeY
analyzeMethod; %handle to analyze() method
end
methods
function obj = DataAnalyzer(dat,analyzeMethod,varargin)
obj = obj@HandleCompatibleSuperClass(dat,varargin{:})
obj.RangeY=analyzeMethod(obj.DomainX);
obj.analyzeMethod=analyzeMethod; %store it to a property for later use, if desired.
end
end
end
  댓글 수: 1
Jacob Lynch August
Jacob Lynch August 16 Feb 2021
  1. To maintain intellectual property, much of this is distributed as p-code, even internally, so editing that isn't feasible. (I know pcode is simply obfuscated, not encrypted.)
  2. Approximator has all the same properties as Analyzer, so should could compute all the same data when using the same method. Inheritance feels like the shortest path to keep all the other functionality of Analyzer, but just employing a shortcut on analyze().
  3. I've been bitten too many times by global and persistent variables to ever trust them, even when I think I'm being clever by time stamping the instantiated object.

댓글을 달려면 로그인하십시오.


Matt J
Matt J 16 Feb 2021
편집: Matt J 16 Feb 2021
It should be enough just to provide an overriding analyze() method in the subclass,
classdef DataApproximator < DataAnalyzer
methods
function obj = DataApproximator(dat,varargin)
obj = obj@DataAnalyzer(dat,varargin{:});
end
function y_results = analyze(obj,x_queries)
y_results = interp1(obj.DomainX,obj.RangeY,x_queries,'linear');
end
% all those other useful methods to analyze data
end
end
  댓글 수: 3
Matt J
Matt J 16 Feb 2021
I'm not proud of this approach.
I think it's pretty good, although I would probably refine it as below. I think some degree of hackery will be inevitable, since if the implementation of the superclass is uneditable, you are blocked from doing things the "right way".
classdef DataApproximator < DataAnalyzer
properties(SetAccess=immutable,GetAccess=private)
DomainX (:,1)
RangeY (:,:)
end
methods
function obj = DataApproximator(x_domain,dat,varargin)
% Construct object
obj = obj@DataAnalyzer(dat,varargin{:});
obj.DomainX = x_domain;
obj.RangeY = analyze(obj,'superclass');
end
function y_results = analyze(obj,varargin)
normalOperation = ~(nargin>1 && strcmp(varargin{1},'superclass') );
if normalOperation
y_results = interp1(obj.DomainX,obj.RangeY,'linear',nan);
else
y_results = analyze@DataAnalyzer(obj,obj.DomainX);
end
end
end
end

댓글을 달려면 로그인하십시오.

제품


릴리스

R2020b

Community Treasure Hunt

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

Start Hunting!

Translated by