Unexpected behaviour of abstract class child class

1 vue (au cours des 30 derniers jours)
Kris
Kris le 17 Août 2015
Disclaimer: I have also posted this question on Stack Overflow:
I am writing some Matlab code to load data from specific file formats such that I can treat the loaded data in a uniform way.
I therefore want to represent the data using an abstract class with unique subclasses for each possible file format.
Central to my scheme is a method that either gets the data from file (the unique bit of the implementation) or, if the data was already loaded, just spits it out. I.e. a sort of lazy loading system since getting data from disk can be slow...
I wanted to setup an abstract class in my Matlab program like so:
classdef TCSPCImageData
properties (SetAccess = protected)
% The same for all subclasses.
frameindex = -1;
framedata = '';
...
end
properties (Abstract, SetAccess = protected)
% Needs to be set by subclass
type
end
methods
% Constructor. Code omitted for brevity
function obj = TCSPCImageData(path)
...
end
function data = frame(obj, idx, tshift)
% Some shared functionality.
if (obj.frameindex == idx)
...
else
% Call a specific subclass method.
data = obj.getframe(idx,tshift);
end
end
end
methods (Abstract, Access = protected)
% The abstract method that will be implemented by each subclass.
getframe(obj, idx, tshift)
end
end
So in summary, there is a method in my superclass with functionality that all subclasses should share but in that method I call a specific implementation, unique to each subclass.
Then a subclass looks like this:
classdef PTUImageData < Data.TCSPCImageData
properties (SetAccess = protected)
% Specific initialisation of this variable
type = 'PTU';
end
methods
% We call the superclass constructor.
function obj = PTUImageData(path)
obj@Data.TCSPCImageData(path);
end
% Apparently, you need to call the superclass method.
function data = frame(obj, idx, tshift)
data = frame@Data.TCSPCImageData(obj, idx, tshift);
end
end
methods(Access = protected)
% The specific implementation.
function data = getframe(obj, idx, tshift)
obj.framedata = 'some value';
end
end
end
Naively, I thought this should work nicely.
However,
obj.framedata = 'some value';
only updates the variable in the scope of the subclass. The value is not maintained when running this code like so:
testdata = Data.PTUImageData('somepath');
testdata.frame(1,1);
Setting a breakpoint inside the subclass shows that obj.framedata gets set but if I check my testdata object later on, testdata.framedata will be empty, which is totally unexpected.
Who can show me the error of my ways?

Réponses (1)

Steven Lord
Steven Lord le 17 Août 2015
Two things:
1) You do set the framedata property in the concrete subclass's getframe method, on the object that was passed into the method. You then promptly exit the getframe method and throw away the modified copy of the object in the method workspace, since you didn't return it and none of the objects involved is a handle object.
2) Not directly related to your question, but some general advise: don't redefine the frame method in your subclass. A PTUImageData ISA Data.TCSPCImageData, and so methods of Data.TCSPCImageData can be called on a PTUImageData directly.
As an example, I have two classes, an abstract base class with an abstract method:
classdef abstractBaseClass
methods(Abstract)
abstractMethod1
end
methods
function concreteMethod1(obj)
disp('Inside abstractBaseClass method concreteMethod1');
end
end
end
and a concrete subclass:
classdef concreteSubclass < abstractBaseClass
methods
function abstractMethod1(obj)
disp('Inside concreteSubclass method abstractMethod1');
end
end
end
Let me instantiate an instance of the subclass:
y = concreteSubclass;
and call the non-abstract method from the superclass.
>> concreteMethod1(y)
Inside abstractBaseClass method concreteMethod1
Note that concreteSubclass didn't redefine that method; the method call invoked the base class method, since a concreteSubclass ISA abstractBaseClass. Now let's call the abstract method that was given a concrete definition in the subclass.
>> abstractMethod1(y)
Inside concreteSubclass method abstractMethod1
Use the methodname@superclass syntax when you want to invoke the superclass method and then do extra work in the subclass method. In the case you've given, that's not the case.

Catégories

En savoir plus sur Construct and Work with Object Arrays dans Help Center et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by