【问题标题】:Unexpected behaviour of Matlab abstract subclassMatlab抽象子类的意外行为
【发布时间】:2015-08-17 07:48:32
【问题描述】:

我正在编写一些 Matlab 代码来从特定文件格式加载数据,以便我可以以统一的方式处理加载的数据。

因此,我想使用一个抽象类来表示数据,该抽象类对于每种可能的文件格式都有唯一的子类。

我的方案的核心是一种从文件中获取数据的方法(实现的唯一位),或者如果数据已经加载,则将其吐出。 IE。一种延迟加载系统,因为从磁盘获取数据可能很慢......

我想在我的 Matlab 程序中设置一个抽象类,如下所示:

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

总而言之,我的超类中有一个方法,其功能是所有子类都应该共享的,但在该方法中,我称之为特定实现,每个子类都是唯一的。

然后一个子类是这样的:

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

天真地,我认为这应该很好用。

但是,obj.framedata = 'some value'; 只更新子类范围内的变量。像这样运行此代码时不会维护该值:

testdata = Data.PTUImageData('somepath');
testdata.frame(1,1);

在子类中设置断点表明 obj.framedata 已设置,但如果我稍后检查我的 testdata 对象,testdata.framedata 将为空,这是完全出乎意料的。

谁能告诉我我的方法的错误?

编辑

正如下面的答案所说,不需要显式调用frame 函数:

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

    end

    methods(Access = protected)

    % The specific implementation.
    function data = getframe(obj, idx, tshift)

        obj.framedata = 'some value';

    end

end
end

【问题讨论】:

    标签: matlab oop abstract-class


    【解决方案1】:

    您需要通过从handle 继承来使您的TCSPCImageData 成为一个句柄 类:

    classdef TCSPCImageData < handle
    

    查看documentation 了解有关句柄类的更多信息。

    默认是一个类是一个value类,这意味着它会有pass-by-value行为。换句话说,它们的行为类似于常规数值数组:

    >> a = 2;
    >> b = a;
    >> a = 3;
    >> b
    b = 
        2
    

    请注意,当您更改a 时,b 并未更改,因为ba副本,而不是对a 本身的引用。它们具有按值传递的行为。

    另一方面,一些其他变量(例如 MATLAB 图形变量)是 句柄 变量,并且具有 pass-by-reference 行为:

    >> a = figure;
    >> get(a,'Name')
    ans =
         ''
    >> b = a;
    >> get(b,'Name')
    ans =
         ''
    >> set(a,'Name', 'hello')
    >> get(b,'Name')
    ans =
    hello
    

    请注意,当您更改 a 的属性时,b 的属性已更改,因为 b 是对 a 的引用,而不是它的副本。它们具有传递引用行为。

    默认情况下,MATLAB 类具有值行为。您可以通过从 handle 继承来赋予它们句柄行为。

    PS 我很确定你不需要在子类PTUImageData 中实现方法frame;它应该只继承 TCSPCImageData 的实现。

    【讨论】:

    • 一分钱掉落的声音 认为我实际上知道 By Value 和 By Ref 因为这也与 C# 相关:-/ 我想我也是有趣的 Matlab 语法使我们感到奇怪。非常感谢!
    • 另外注意:matlab 似乎不喜欢在你的代码文件中添加
    • 你对“框架”功能也是正确的。它会自动继承,这似乎是合乎逻辑的......
    • 关于clear 的主题:是的,当您在工作区中存在某个类的变量并且您更改了类定义时,在您删除这些变量之前不会应用更改 - 您如果您尝试使用它们,将会收到某种警告。 clear 通常会删除大部分内容;但clear classes 明确强制更新所有类定义。
    猜你喜欢
    • 1970-01-01
    • 2022-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-18
    • 2019-10-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多